Merge e08466a7c0 ("Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma") into android-mainline
Steps on the way to 6.1-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I61a8b8358820f1f519fcd58cc1c3ecc8a7f1f4c6
This commit is contained in:
commit
5fdc923f23
884 changed files with 23776 additions and 6187 deletions
123
Documentation/devicetree/bindings/ata/ahci-common.yaml
Normal file
123
Documentation/devicetree/bindings/ata/ahci-common.yaml
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/ata/ahci-common.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Common Properties for Serial ATA AHCI controllers
|
||||
|
||||
maintainers:
|
||||
- Hans de Goede <hdegoede@redhat.com>
|
||||
- Damien Le Moal <damien.lemoal@opensource.wdc.com>
|
||||
|
||||
description:
|
||||
This document defines device tree properties for a common AHCI SATA
|
||||
controller implementation. It's hardware interface is supposed to
|
||||
conform to the technical standard defined by Intel (see Serial ATA
|
||||
Advanced Host Controller Interface specification for details). The
|
||||
document doesn't constitute a DT-node binding by itself but merely
|
||||
defines a set of common properties for the AHCI-compatible devices.
|
||||
|
||||
select: false
|
||||
|
||||
allOf:
|
||||
- $ref: sata-common.yaml#
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description:
|
||||
Generic AHCI registers space conforming to the Serial ATA AHCI
|
||||
specification.
|
||||
|
||||
reg-names:
|
||||
description: CSR space IDs
|
||||
contains:
|
||||
const: ahci
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
Generic AHCI state change interrupt. Can be implemented either as a
|
||||
single line attached to the controller or as a set of the signals
|
||||
indicating the particular port events.
|
||||
minItems: 1
|
||||
maxItems: 32
|
||||
|
||||
ahci-supply:
|
||||
description: Power regulator for AHCI controller
|
||||
|
||||
target-supply:
|
||||
description: Power regulator for SATA target device
|
||||
|
||||
phy-supply:
|
||||
description: Power regulator for SATA PHY
|
||||
|
||||
phys:
|
||||
description: Reference to the SATA PHY node
|
||||
maxItems: 1
|
||||
|
||||
phy-names:
|
||||
const: sata-phy
|
||||
|
||||
hba-cap:
|
||||
$ref: '/schemas/types.yaml#/definitions/uint32'
|
||||
description:
|
||||
Bitfield of the HBA generic platform capabilities like Staggered
|
||||
Spin-up or Mechanical Presence Switch support. It can be used to
|
||||
appropriately initialize the HWinit fields of the HBA CAP register
|
||||
in case if the system firmware hasn't done it.
|
||||
|
||||
ports-implemented:
|
||||
$ref: '/schemas/types.yaml#/definitions/uint32'
|
||||
description:
|
||||
Mask that indicates which ports the HBA supports. Useful if PI is not
|
||||
programmed by the BIOS, which is true for some embedded SoC's.
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[0-9a-f]+$":
|
||||
$ref: '#/$defs/ahci-port'
|
||||
description:
|
||||
It is optionally possible to describe the ports as sub-nodes so
|
||||
to enable each port independently when dealing with multiple PHYs.
|
||||
|
||||
required:
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
$defs:
|
||||
ahci-port:
|
||||
$ref: /schemas/ata/sata-common.yaml#/$defs/sata-port
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description:
|
||||
AHCI SATA port identifier. By design AHCI controller can't have
|
||||
more than 32 ports due to the CAP.NP fields and PI register size
|
||||
constraints.
|
||||
minimum: 0
|
||||
maximum: 31
|
||||
|
||||
phys:
|
||||
description: Individual AHCI SATA port PHY
|
||||
maxItems: 1
|
||||
|
||||
phy-names:
|
||||
description: AHCI SATA port PHY ID
|
||||
const: sata-phy
|
||||
|
||||
target-supply:
|
||||
description: Power regulator for SATA port target device
|
||||
|
||||
hba-port-cap:
|
||||
$ref: '/schemas/types.yaml#/definitions/uint32'
|
||||
description:
|
||||
Bitfield of the HBA port-specific platform capabilities like Hot
|
||||
plugging, eSATA, FIS-based Switching, etc (see AHCI specification
|
||||
for details). It can be used to initialize the HWinit fields of
|
||||
the PxCMD register in case if the system firmware hasn't done it.
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
...
|
||||
|
|
@ -30,14 +30,11 @@ select:
|
|||
- marvell,armada-3700-ahci
|
||||
- marvell,armada-8k-ahci
|
||||
- marvell,berlin2q-ahci
|
||||
- snps,dwc-ahci
|
||||
- snps,spear-ahci
|
||||
required:
|
||||
- compatible
|
||||
|
||||
allOf:
|
||||
- $ref: "sata-common.yaml#"
|
||||
|
||||
- $ref: "ahci-common.yaml#"
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -49,17 +46,11 @@ properties:
|
|||
- marvell,berlin2-ahci
|
||||
- marvell,berlin2q-ahci
|
||||
- const: generic-ahci
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rk3568-dwc-ahci
|
||||
- const: snps,dwc-ahci
|
||||
- enum:
|
||||
- cavium,octeon-7130-ahci
|
||||
- hisilicon,hisi-ahci
|
||||
- ibm,476gtr-ahci
|
||||
- marvell,armada-3700-ahci
|
||||
- snps,dwc-ahci
|
||||
- snps,spear-ahci
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
|
|
@ -69,92 +60,37 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description:
|
||||
Clock IDs array as required by the controller.
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
description:
|
||||
Names of clocks corresponding to IDs in the clock property.
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
ahci-supply:
|
||||
description:
|
||||
regulator for AHCI controller
|
||||
|
||||
dma-coherent: true
|
||||
|
||||
phy-supply:
|
||||
description:
|
||||
regulator for PHY power
|
||||
|
||||
phys:
|
||||
description:
|
||||
List of all PHYs on this controller
|
||||
maxItems: 1
|
||||
|
||||
phy-names:
|
||||
description:
|
||||
Name specifier for the PHYs
|
||||
maxItems: 1
|
||||
|
||||
ports-implemented:
|
||||
$ref: '/schemas/types.yaml#/definitions/uint32'
|
||||
description: |
|
||||
Mask that indicates which ports that the HBA supports
|
||||
are available for software to use. Useful if PORTS_IMPL
|
||||
is not programmed by the BIOS, which is true with
|
||||
some embedded SoCs.
|
||||
maximum: 0x1f
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
target-supply:
|
||||
description:
|
||||
regulator for SATA target power
|
||||
patternProperties:
|
||||
"^sata-port@[0-9a-f]+$":
|
||||
$ref: /schemas/ata/ahci-common.yaml#/$defs/ahci-port
|
||||
|
||||
anyOf:
|
||||
- required: [ phys ]
|
||||
- required: [ target-supply ]
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description:
|
||||
Subnode with configuration of the Ports.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
phys:
|
||||
maxItems: 1
|
||||
|
||||
phy-names:
|
||||
maxItems: 1
|
||||
|
||||
target-supply:
|
||||
description:
|
||||
regulator for SATA target power
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
anyOf:
|
||||
- required: [ phys ]
|
||||
- required: [ target-supply ]
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
|
@ -167,6 +103,8 @@ examples:
|
|||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/berlin2q.h>
|
||||
#include <dt-bindings/ata/ahci.h>
|
||||
|
||||
sata@f7e90000 {
|
||||
compatible = "marvell,berlin2q-ahci", "generic-ahci";
|
||||
reg = <0xf7e90000 0x1000>;
|
||||
|
|
@ -175,15 +113,23 @@ examples:
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hba-cap = <HBA_SMPS>;
|
||||
|
||||
sata0: sata-port@0 {
|
||||
reg = <0>;
|
||||
|
||||
phys = <&sata_phy 0>;
|
||||
target-supply = <®_sata0>;
|
||||
|
||||
hba-port-cap = <(HBA_PORT_FBSCP | HBA_PORT_ESP)>;
|
||||
};
|
||||
|
||||
sata1: sata-port@1 {
|
||||
reg = <1>;
|
||||
|
||||
phys = <&sata_phy 1>;
|
||||
target-supply = <®_sata1>;
|
||||
|
||||
hba-port-cap = <(HBA_PORT_HPCP | HBA_PORT_MPSP | HBA_PORT_FBSCP)>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
115
Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
Normal file
115
Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/ata/baikal,bt1-ahci.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Baikal-T1 SoC AHCI SATA controller
|
||||
|
||||
maintainers:
|
||||
- Serge Semin <fancer.lancer@gmail.com>
|
||||
|
||||
description:
|
||||
AHCI SATA controller embedded into the Baikal-T1 SoC is based on the
|
||||
DWC AHCI SATA v4.10a IP-core.
|
||||
|
||||
allOf:
|
||||
- $ref: snps,dwc-ahci-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: baikal,bt1-ahci
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Peripheral APB bus clock
|
||||
- description: Application AXI BIU clock
|
||||
- description: SATA Ports reference clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: aclk
|
||||
- const: ref
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: Application AXI BIU domain reset
|
||||
- description: SATA Ports clock domain reset
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: arst
|
||||
- const: ref
|
||||
|
||||
ports-implemented:
|
||||
maximum: 0x3
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[0-1]$":
|
||||
$ref: /schemas/ata/snps,dwc-ahci-common.yaml#/$defs/dwc-ahci-port
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
|
||||
snps,tx-ts-max:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
Due to having AXI3 bus interface utilized the maximum Tx DMA
|
||||
transaction size can't exceed 16 beats (AxLEN[3:0]).
|
||||
enum: [ 1, 2, 4, 8, 16 ]
|
||||
|
||||
snps,rx-ts-max:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
Due to having AXI3 bus interface utilized the maximum Rx DMA
|
||||
transaction size can't exceed 16 beats (AxLEN[3:0]).
|
||||
enum: [ 1, 2, 4, 8, 16 ]
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sata@1f050000 {
|
||||
compatible = "baikal,bt1-ahci";
|
||||
reg = <0x1f050000 0x2000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
interrupts = <0 64 4>;
|
||||
|
||||
clocks = <&ccu_sys 1>, <&ccu_axi 2>, <&sata_ref_clk>;
|
||||
clock-names = "pclk", "aclk", "ref";
|
||||
|
||||
resets = <&ccu_axi 2>, <&ccu_sys 0>;
|
||||
reset-names = "arst", "ref";
|
||||
|
||||
ports-implemented = <0x3>;
|
||||
|
||||
sata-port@0 {
|
||||
reg = <0>;
|
||||
|
||||
snps,tx-ts-max = <4>;
|
||||
snps,rx-ts-max = <4>;
|
||||
};
|
||||
|
||||
sata-port@1 {
|
||||
reg = <1>;
|
||||
|
||||
snps,tx-ts-max = <4>;
|
||||
snps,rx-ts-max = <4>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -14,7 +14,7 @@ maintainers:
|
|||
- Florian Fainelli <f.fainelli@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: sata-common.yaml#
|
||||
- $ref: ahci-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -41,8 +41,6 @@ properties:
|
|||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
dma-coherent: true
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
|||
|
|
@ -31,22 +31,27 @@ properties:
|
|||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
dma-coherent: true
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[0-9a-e]$":
|
||||
$ref: '#/$defs/sata-port'
|
||||
description: |
|
||||
DT nodes for ports connected on the SATA host. The SATA port
|
||||
nodes will be named "sata-port".
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
$defs:
|
||||
sata-port:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 14
|
||||
description:
|
||||
The ID number of the drive port SATA can potentially use a port
|
||||
multiplier making it possible to connect up to 15 disks to a single
|
||||
SATA port.
|
||||
|
||||
additionalProperties: true
|
||||
The ID number of the SATA port. Aside with being directly used,
|
||||
each port can have a Port Multiplier attached thus allowing to
|
||||
access more than one drive by means of a single SATA port.
|
||||
|
||||
...
|
||||
|
|
|
|||
102
Documentation/devicetree/bindings/ata/snps,dwc-ahci-common.yaml
Normal file
102
Documentation/devicetree/bindings/ata/snps,dwc-ahci-common.yaml
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/ata/snps,dwc-ahci-common.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Synopsys DWC AHCI SATA controller properties
|
||||
|
||||
maintainers:
|
||||
- Serge Semin <fancer.lancer@gmail.com>
|
||||
|
||||
description:
|
||||
This document defines device tree schema for the generic Synopsys DWC
|
||||
AHCI controller properties.
|
||||
|
||||
select: false
|
||||
|
||||
allOf:
|
||||
- $ref: ahci-common.yaml#
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description:
|
||||
Basic DWC AHCI SATA clock sources like application AXI/AHB BIU clock,
|
||||
PM-alive clock, RxOOB detection clock, embedded PHYs reference (Rx/Tx)
|
||||
clock, etc.
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
oneOf:
|
||||
- description: Application APB/AHB/AXI BIU clock
|
||||
enum:
|
||||
- pclk
|
||||
- aclk
|
||||
- hclk
|
||||
- sata
|
||||
- description: Power Module keep-alive clock
|
||||
const: pmalive
|
||||
- description: RxOOB detection clock
|
||||
const: rxoob
|
||||
- description: SATA Ports reference clock
|
||||
const: ref
|
||||
|
||||
resets:
|
||||
description:
|
||||
At least basic application and reference clock domains resets are
|
||||
normally supported by the DWC AHCI SATA controller.
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
oneOf:
|
||||
- description: Application AHB/AXI BIU clock domain reset control
|
||||
enum:
|
||||
- arst
|
||||
- hrst
|
||||
- description: Power Module keep-alive clock domain reset control
|
||||
const: pmalive
|
||||
- description: RxOOB detection clock domain reset control
|
||||
const: rxoob
|
||||
- description: Reference clock domain reset control
|
||||
const: ref
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[0-9a-e]$":
|
||||
$ref: '#/$defs/dwc-ahci-port'
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
$defs:
|
||||
dwc-ahci-port:
|
||||
$ref: /schemas/ata/ahci-common.yaml#/$defs/ahci-port
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
snps,tx-ts-max:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Maximal size of Tx DMA transactions in FIFO words
|
||||
enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
|
||||
|
||||
snps,rx-ts-max:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Maximal size of Rx DMA transactions in FIFO words
|
||||
enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
|
||||
|
||||
...
|
||||
75
Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
Normal file
75
Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/ata/snps,dwc-ahci.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Synopsys DWC AHCI SATA controller
|
||||
|
||||
maintainers:
|
||||
- Serge Semin <fancer.lancer@gmail.com>
|
||||
|
||||
description:
|
||||
This document defines device tree bindings for the generic Synopsys DWC
|
||||
implementation of the AHCI SATA controller.
|
||||
|
||||
allOf:
|
||||
- $ref: snps,dwc-ahci-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: Synopsys AHCI SATA-compatible devices
|
||||
const: snps,dwc-ahci
|
||||
- description: SPEAr1340 AHCI SATA device
|
||||
const: snps,spear-ahci
|
||||
- description: Rockhip RK3568 AHCI controller
|
||||
items:
|
||||
- const: rockchip,rk3568-dwc-ahci
|
||||
- const: snps,dwc-ahci
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[0-9a-e]$":
|
||||
$ref: /schemas/ata/snps,dwc-ahci-common.yaml#/$defs/dwc-ahci-port
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/ata/ahci.h>
|
||||
|
||||
sata@122f0000 {
|
||||
compatible = "snps,dwc-ahci";
|
||||
reg = <0x122F0000 0x1ff>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
clocks = <&clock1>, <&clock2>;
|
||||
clock-names = "aclk", "ref";
|
||||
|
||||
phys = <&sata_phy>;
|
||||
phy-names = "sata-phy";
|
||||
|
||||
ports-implemented = <0x1>;
|
||||
|
||||
sata-port@0 {
|
||||
reg = <0>;
|
||||
|
||||
hba-port-cap = <HBA_PORT_FBSCP>;
|
||||
|
||||
snps,tx-ts-max = <512>;
|
||||
snps,rx-ts-max = <512>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/mediatek,mdp3-rdma.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek Read Direct Memory Access
|
||||
|
||||
maintainers:
|
||||
- Matthias Brugger <matthias.bgg@gmail.com>
|
||||
- Moudy Ho <moudy.ho@mediatek.com>
|
||||
|
||||
description: |
|
||||
MediaTek Read Direct Memory Access(RDMA) component used to do read DMA.
|
||||
It contains one line buffer to store the sufficient pixel data, and
|
||||
must be siblings to the central MMSYS_CONFIG node.
|
||||
For a description of the MMSYS_CONFIG binding, see
|
||||
Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
|
||||
for details.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: mediatek,mt8183-mdp3-rdma
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
mediatek,gce-client-reg:
|
||||
$ref: '/schemas/types.yaml#/definitions/phandle-array'
|
||||
items:
|
||||
items:
|
||||
- description: phandle of GCE
|
||||
- description: GCE subsys id
|
||||
- description: register offset
|
||||
- description: register size
|
||||
description: The register of client driver can be configured by gce with
|
||||
4 arguments defined in this property. Each GCE subsys id is mapping to
|
||||
a client defined in the header include/dt-bindings/gce/<chip>-gce.h.
|
||||
|
||||
mediatek,gce-events:
|
||||
description:
|
||||
The event id which is mapping to the specific hardware event signal
|
||||
to gce. The event id is defined in the gce header
|
||||
include/dt-bindings/gce/<chip>-gce.h of each chips.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: RDMA clock
|
||||
- description: RSZ clock
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
mboxes:
|
||||
items:
|
||||
- description: used for 1st data pipe from RDMA
|
||||
- description: used for 2nd data pipe from RDMA
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- mediatek,gce-client-reg
|
||||
- mediatek,gce-events
|
||||
- power-domains
|
||||
- clocks
|
||||
- iommus
|
||||
- mboxes
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mt8183-clk.h>
|
||||
#include <dt-bindings/gce/mt8183-gce.h>
|
||||
#include <dt-bindings/power/mt8183-power.h>
|
||||
#include <dt-bindings/memory/mt8183-larb-port.h>
|
||||
|
||||
mdp3_rdma0: mdp3-rdma0@14001000 {
|
||||
compatible = "mediatek,mt8183-mdp3-rdma";
|
||||
reg = <0x14001000 0x1000>;
|
||||
mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x1000 0x1000>;
|
||||
mediatek,gce-events = <CMDQ_EVENT_MDP_RDMA0_SOF>,
|
||||
<CMDQ_EVENT_MDP_RDMA0_EOF>;
|
||||
power-domains = <&spm MT8183_POWER_DOMAIN_DISP>;
|
||||
clocks = <&mmsys CLK_MM_MDP_RDMA0>,
|
||||
<&mmsys CLK_MM_MDP_RSZ1>;
|
||||
iommus = <&iommu>;
|
||||
mboxes = <&gce 20 CMDQ_THR_PRIO_LOWEST>,
|
||||
<&gce 21 CMDQ_THR_PRIO_LOWEST>;
|
||||
};
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/mediatek,mdp3-rsz.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek Resizer
|
||||
|
||||
maintainers:
|
||||
- Matthias Brugger <matthias.bgg@gmail.com>
|
||||
- Moudy Ho <moudy.ho@mediatek.com>
|
||||
|
||||
description: |
|
||||
One of Media Data Path 3 (MDP3) components used to do frame resizing.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- mediatek,mt8183-mdp3-rsz
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
mediatek,gce-client-reg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
items:
|
||||
items:
|
||||
- description: phandle of GCE
|
||||
- description: GCE subsys id
|
||||
- description: register offset
|
||||
- description: register size
|
||||
description: The register of client driver can be configured by gce with
|
||||
4 arguments defined in this property. Each GCE subsys id is mapping to
|
||||
a client defined in the header include/dt-bindings/gce/<chip>-gce.h.
|
||||
|
||||
mediatek,gce-events:
|
||||
description:
|
||||
The event id which is mapping to the specific hardware event signal
|
||||
to gce. The event id is defined in the gce header
|
||||
include/dt-bindings/gce/<chip>-gce.h of each chips.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- mediatek,gce-client-reg
|
||||
- mediatek,gce-events
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mt8183-clk.h>
|
||||
#include <dt-bindings/gce/mt8183-gce.h>
|
||||
|
||||
mdp3_rsz0: mdp3-rsz0@14003000 {
|
||||
compatible = "mediatek,mt8183-mdp3-rsz";
|
||||
reg = <0x14003000 0x1000>;
|
||||
mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x3000 0x1000>;
|
||||
mediatek,gce-events = <CMDQ_EVENT_MDP_RSZ0_SOF>,
|
||||
<CMDQ_EVENT_MDP_RSZ0_EOF>;
|
||||
clocks = <&mmsys CLK_MM_MDP_RSZ0>;
|
||||
};
|
||||
|
||||
mdp3_rsz1: mdp3-rsz1@14004000 {
|
||||
compatible = "mediatek,mt8183-mdp3-rsz";
|
||||
reg = <0x14004000 0x1000>;
|
||||
mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x4000 0x1000>;
|
||||
mediatek,gce-events = <CMDQ_EVENT_MDP_RSZ1_SOF>,
|
||||
<CMDQ_EVENT_MDP_RSZ1_EOF>;
|
||||
clocks = <&mmsys CLK_MM_MDP_RSZ1>;
|
||||
};
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/mediatek,mdp3-wrot.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek Write DMA with Rotation
|
||||
|
||||
maintainers:
|
||||
- Matthias Brugger <matthias.bgg@gmail.com>
|
||||
- Moudy Ho <moudy.ho@mediatek.com>
|
||||
|
||||
description: |
|
||||
One of Media Data Path 3 (MDP3) components used to write DMA with frame rotation.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- mediatek,mt8183-mdp3-wrot
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
mediatek,gce-client-reg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
items:
|
||||
items:
|
||||
- description: phandle of GCE
|
||||
- description: GCE subsys id
|
||||
- description: register offset
|
||||
- description: register size
|
||||
description: The register of client driver can be configured by gce with
|
||||
4 arguments defined in this property. Each GCE subsys id is mapping to
|
||||
a client defined in the header include/dt-bindings/gce/<chip>-gce.h.
|
||||
|
||||
mediatek,gce-events:
|
||||
description:
|
||||
The event id which is mapping to the specific hardware event signal
|
||||
to gce. The event id is defined in the gce header
|
||||
include/dt-bindings/gce/<chip>-gce.h of each chips.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- mediatek,gce-client-reg
|
||||
- mediatek,gce-events
|
||||
- power-domains
|
||||
- clocks
|
||||
- iommus
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mt8183-clk.h>
|
||||
#include <dt-bindings/gce/mt8183-gce.h>
|
||||
#include <dt-bindings/power/mt8183-power.h>
|
||||
#include <dt-bindings/memory/mt8183-larb-port.h>
|
||||
|
||||
mdp3_wrot0: mdp3-wrot0@14005000 {
|
||||
compatible = "mediatek,mt8183-mdp3-wrot";
|
||||
reg = <0x14005000 0x1000>;
|
||||
mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x5000 0x1000>;
|
||||
mediatek,gce-events = <CMDQ_EVENT_MDP_WROT0_SOF>,
|
||||
<CMDQ_EVENT_MDP_WROT0_EOF>;
|
||||
power-domains = <&spm MT8183_POWER_DOMAIN_DISP>;
|
||||
clocks = <&mmsys CLK_MM_MDP_WROT0>;
|
||||
iommus = <&iommu>;
|
||||
};
|
||||
|
|
@ -20,6 +20,7 @@ properties:
|
|||
- mediatek,mt8173-vcodec-enc-vp8
|
||||
- mediatek,mt8173-vcodec-enc
|
||||
- mediatek,mt8183-vcodec-enc
|
||||
- mediatek,mt8188-vcodec-enc
|
||||
- mediatek,mt8192-vcodec-enc
|
||||
- mediatek,mt8195-vcodec-enc
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ properties:
|
|||
enum:
|
||||
- mediatek,mt8192-vcodec-dec
|
||||
- mediatek,mt8186-vcodec-dec
|
||||
- mediatek,mt8188-vcodec-dec
|
||||
- mediatek,mt8195-vcodec-dec
|
||||
|
||||
reg:
|
||||
|
|
|
|||
69
Documentation/devicetree/bindings/media/nxp,dw100.yaml
Normal file
69
Documentation/devicetree/bindings/media/nxp,dw100.yaml
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/nxp,dw100.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP i.MX8MP DW100 Dewarper core
|
||||
|
||||
maintainers:
|
||||
- Xavier Roumegue <xavier.roumegue@oss.nxp.com>
|
||||
|
||||
description: |-
|
||||
The Dewarp Engine provides high-performance dewarp processing for the
|
||||
correction of the distortion that is introduced in images produced by fisheye
|
||||
and wide angle lenses. It is implemented with a line/tile-cache based
|
||||
architecture. With configurable address mapping look up tables and per tile
|
||||
processing, it successfully generates a corrected output image.
|
||||
The engine can be used to perform scaling, cropping and pixel format
|
||||
conversion.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- nxp,imx8mp-dw100
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: The AXI clock
|
||||
- description: The AHB clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: axi
|
||||
- const: ahb
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8mp-clock.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/imx8mp-power.h>
|
||||
|
||||
dewarp: dwe@32e30000 {
|
||||
compatible = "nxp,imx8mp-dw100";
|
||||
reg = <0x32e30000 0x10000>;
|
||||
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
|
||||
clock-names = "axi", "ahb";
|
||||
power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_DWE>;
|
||||
};
|
||||
|
|
@ -17,6 +17,7 @@ description:
|
|||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- renesas,r9a07g044-vsp2 # RZ/G2L
|
||||
- renesas,vsp1 # R-Car Gen2 and RZ/G1
|
||||
- renesas,vsp2 # R-Car Gen3 and RZ/G2
|
||||
|
||||
|
|
@ -26,8 +27,8 @@ properties:
|
|||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clocks: true
|
||||
clock-names: true
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
|
@ -50,17 +51,43 @@ required:
|
|||
|
||||
additionalProperties: false
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: renesas,vsp1
|
||||
then:
|
||||
properties:
|
||||
renesas,fcp: false
|
||||
else:
|
||||
required:
|
||||
- renesas,fcp
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,vsp1
|
||||
then:
|
||||
properties:
|
||||
renesas,fcp: false
|
||||
else:
|
||||
required:
|
||||
- renesas,fcp
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a07g044-vsp2
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Main clock
|
||||
- description: Register access clock
|
||||
- description: Video clock
|
||||
clock-names:
|
||||
items:
|
||||
- const: aclk
|
||||
- const: pclk
|
||||
- const: vclk
|
||||
required:
|
||||
- clock-names
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names: false
|
||||
|
||||
examples:
|
||||
# R8A7790 (R-Car H2) VSP1-S
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ properties:
|
|||
patternProperties:
|
||||
"^.*_(clk|rst)$":
|
||||
type: object
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -34,6 +35,45 @@ patternProperties:
|
|||
- fixed-factor-clock
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: fixed-factor-clock
|
||||
|
||||
then:
|
||||
$ref: /schemas/clock/fixed-factor-clock.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: allwinner,sun4i-a10-mod0-clk
|
||||
|
||||
then:
|
||||
properties:
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
# Already checked in the main schema
|
||||
compatible: true
|
||||
|
||||
clocks:
|
||||
maxItems: 2
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
|
||||
phandle: true
|
||||
|
||||
required:
|
||||
- "#clock-cells"
|
||||
- compatible
|
||||
- clocks
|
||||
- clock-output-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ properties:
|
|||
patternProperties:
|
||||
"^.*(clk|rst|codec).*$":
|
||||
type: object
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -36,6 +37,15 @@ patternProperties:
|
|||
- compatible
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: fixed-factor-clock
|
||||
|
||||
then:
|
||||
$ref: /schemas/clock/fixed-factor-clock.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
|||
110
Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
Normal file
110
Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/aspeed,ast2x00-scu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Aspeed System Control Unit
|
||||
|
||||
description:
|
||||
The Aspeed System Control Unit manages the global behaviour of the SoC,
|
||||
configuring elements such as clocks, pinmux, and reset.
|
||||
|
||||
maintainers:
|
||||
- Joel Stanley <joel@jms.id.au>
|
||||
- Andrew Jeffery <andrew@aj.id.au>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- aspeed,ast2400-scu
|
||||
- aspeed,ast2500-scu
|
||||
- aspeed,ast2600-scu
|
||||
- const: syscon
|
||||
- const: simple-mfd
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
ranges: true
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
|
||||
patternProperties:
|
||||
'^p2a-control@[0-9a-f]+$':
|
||||
description: See Documentation/devicetree/bindings/misc/aspeed-p2a-ctrl.txt
|
||||
type: object
|
||||
|
||||
'^pinctrl(@[0-9a-f]+)?$':
|
||||
oneOf:
|
||||
- $ref: /schemas/pinctrl/aspeed,ast2400-pinctrl.yaml
|
||||
- $ref: /schemas/pinctrl/aspeed,ast2500-pinctrl.yaml
|
||||
- $ref: /schemas/pinctrl/aspeed,ast2600-pinctrl.yaml
|
||||
|
||||
'^interrupt-controller@[0-9a-f]+$':
|
||||
description: See Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2xxx-scu-ic.txt
|
||||
type: object
|
||||
|
||||
'^silicon-id@[0-9a-f]+$':
|
||||
description: Unique hardware silicon identifiers within the SoC
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- aspeed,ast2400-silicon-id
|
||||
- aspeed,ast2500-silicon-id
|
||||
- aspeed,ast2600-silicon-id
|
||||
- const: aspeed,silicon-id
|
||||
|
||||
reg:
|
||||
description:
|
||||
The reg should be the unique silicon id register, and not backwards
|
||||
compatible one in eg. the 2600.
|
||||
minItems: 1
|
||||
items:
|
||||
- description: silicon id information registers
|
||||
- description: unique chip id registers
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- ranges
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
syscon@1e6e2000 {
|
||||
compatible = "aspeed,ast2400-scu", "syscon", "simple-mfd";
|
||||
reg = <0x1e6e2000 0x1a8>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x1e6e2000 0x1000>;
|
||||
|
||||
silicon-id@7c {
|
||||
compatible = "aspeed,ast2500-silicon-id", "aspeed,silicon-id";
|
||||
reg = <0x7c 0x4>, <0x150 0x8>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
The Aspeed System Control Unit manages the global behaviour of the SoC,
|
||||
configuring elements such as clocks, pinmux, and reset.
|
||||
|
||||
Required properties:
|
||||
- compatible: One of:
|
||||
"aspeed,ast2400-scu", "syscon", "simple-mfd"
|
||||
"aspeed,ast2500-scu", "syscon", "simple-mfd"
|
||||
|
||||
- reg: contains the offset and length of the SCU memory region
|
||||
- #clock-cells: should be set to <1> - the system controller is also a
|
||||
clock provider
|
||||
- #reset-cells: should be set to <1> - the system controller is also a
|
||||
reset line provider
|
||||
|
||||
Example:
|
||||
|
||||
syscon: syscon@1e6e2000 {
|
||||
compatible = "aspeed,ast2400-scu", "syscon", "simple-mfd";
|
||||
reg = <0x1e6e2000 0x1a8>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
Silicon ID
|
||||
-----------------
|
||||
|
||||
Families have unique hardware silicon identifiers within the SoC.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "aspeed,silicon-id" or:
|
||||
"aspeed,ast2400-silicon-id" or
|
||||
"aspeed,ast2500-silicon-id" or
|
||||
"aspeed,ast2600-silicon-id"
|
||||
|
||||
- reg: offset and length of the silicon id information
|
||||
optionally, a second offset and length describes the unique chip id
|
||||
|
||||
The reg should be the unique silicon id register, and
|
||||
not backwards compatible one in eg. the 2600.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
silicon-id@7c {
|
||||
compatible = "aspeed,ast2500-silicon-id", "aspeed,silicon-id";
|
||||
reg = <0x7c 0x4 0x150 0x8>;
|
||||
};
|
||||
|
|
@ -144,6 +144,7 @@ properties:
|
|||
CODECs digital core if not being provided by an internal regulator.
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
|
|
@ -161,6 +162,7 @@ properties:
|
|||
CODECs MICVDD.
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
|
|
@ -177,6 +179,7 @@ properties:
|
|||
Initialisation data for the MIC1VDD supplies.
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
|
|
@ -202,6 +205,7 @@ properties:
|
|||
Initialisation data for the MIC2VDD supplies.
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
|
|
@ -228,6 +232,7 @@ properties:
|
|||
the CODECs analog and 1.8V digital supplies.
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
|
|
|
|||
|
|
@ -71,8 +71,9 @@ properties:
|
|||
|
||||
regulators:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
patternProperties:
|
||||
"^(ldo[1-11]|bcore[1-2]|bpro|bmem|bio|bperi)$":
|
||||
"^(ldo([1-9]|1[01])|bcore([1-2]|s-merged)|b(pro|mem|io|peri)|bmem-bio-merged)$":
|
||||
$ref: /schemas/regulator/regulator.yaml
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
|
@ -112,7 +113,7 @@ examples:
|
|||
};
|
||||
|
||||
regulators {
|
||||
regulator-bcore1 {
|
||||
bcore1 {
|
||||
regulator-name = "BCORE1";
|
||||
regulator-min-microvolt = <300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
|
|
@ -120,7 +121,7 @@ examples:
|
|||
regulator-max-microamp = <2000000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
regulator-ldo11 {
|
||||
ldo11 {
|
||||
regulator-name = "LDO_11";
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <3600000>;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ properties:
|
|||
|
||||
adc:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: Optional hardware monitoring module
|
||||
|
||||
properties:
|
||||
|
|
@ -59,8 +60,9 @@ properties:
|
|||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-9]+$":
|
||||
"^channel@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: |
|
||||
Properties for a single ADC which can report cooked values
|
||||
(i.e. temperature sensor based on thermister), raw values
|
||||
|
|
@ -113,6 +115,7 @@ properties:
|
|||
patternProperties:
|
||||
"^fan-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: Optional fan controller
|
||||
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ properties:
|
|||
|
||||
extcon:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ properties:
|
|||
|
||||
motor-driver:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
compatible:
|
||||
const: maxim,max77843-haptic
|
||||
|
|
|
|||
280
Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
Normal file
280
Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/mediatek,mt6370.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT6370 SubPMIC
|
||||
|
||||
maintainers:
|
||||
- ChiYuan Huang <cy_huang@richtek.com>
|
||||
|
||||
description: |
|
||||
MT6370 is a highly-integrated smart power management IC, which includes a
|
||||
single cell Li-Ion/Li-Polymer switching battery charger, a USB Type-C &
|
||||
Power Delivery (PD) controller, dual flash LED current sources, a RGB LED
|
||||
driver, a backlight WLED driver, a display bias driver and a general LDO for
|
||||
portable devices.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6370
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 1
|
||||
|
||||
adc:
|
||||
type: object
|
||||
description: |
|
||||
Provides 9 channels for system monitoring, including VBUSDIV5 (lower
|
||||
accuracy, higher measure range), VBUSDIV2 (higher accuracy, lower
|
||||
measure range), VBAT, VSYS, CHG_VDDP, TS_BAT, IBUS, IBAT, and TEMP_JC.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6370-adc
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#io-channel-cells"
|
||||
|
||||
backlight:
|
||||
type: object
|
||||
$ref: /schemas/leds/backlight/mediatek,mt6370-backlight.yaml#
|
||||
|
||||
charger:
|
||||
type: object
|
||||
$ref: /schemas/power/supply/mediatek,mt6370-charger.yaml#
|
||||
|
||||
tcpc:
|
||||
type: object
|
||||
$ref: /schemas/usb/mediatek,mt6370-tcpc.yaml#
|
||||
|
||||
indicator:
|
||||
type: object
|
||||
$ref: /schemas/leds/mediatek,mt6370-indicator.yaml#
|
||||
|
||||
flashlight:
|
||||
type: object
|
||||
$ref: /schemas/leds/mediatek,mt6370-flashlight.yaml#
|
||||
|
||||
regulators:
|
||||
type: object
|
||||
description: |
|
||||
List all supported regulators, which support the control for DisplayBias
|
||||
voltages and one general purpose LDO which commonly used to drive the
|
||||
vibrator.
|
||||
|
||||
patternProperties:
|
||||
"^(dsvbst|vibldo)$":
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
type: object
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^(dsvpos|dsvneg)$":
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
type: object
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-controller
|
||||
- "#interrupt-cells"
|
||||
- regulators
|
||||
- adc
|
||||
- backlight
|
||||
- indicator
|
||||
- tcpc
|
||||
- charger
|
||||
- flashlight
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/iio/adc/mediatek,mt6370_adc.h>
|
||||
#include <dt-bindings/usb/pd.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@34 {
|
||||
compatible = "mediatek,mt6370";
|
||||
reg = <0x34>;
|
||||
wakeup-source;
|
||||
interrupts-extended = <&gpio26 3 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
mt6370_adc: adc {
|
||||
compatible = "mediatek,mt6370-adc";
|
||||
#io-channel-cells = <1>;
|
||||
};
|
||||
|
||||
backlight {
|
||||
compatible = "mediatek,mt6370-backlight";
|
||||
mediatek,bled-channel-use = /bits/ 8 <15>;
|
||||
};
|
||||
|
||||
charger {
|
||||
compatible = "mediatek,mt6370-charger";
|
||||
interrupts = <48>, <68>, <6>;
|
||||
interrupt-names = "attach_i", "uvp_d_evt", "mivr";
|
||||
io-channels = <&mt6370_adc MT6370_CHAN_IBUS>;
|
||||
|
||||
mt6370_otg_vbus: usb-otg-vbus-regulator {
|
||||
regulator-name = "mt6370-usb-otg-vbus";
|
||||
regulator-min-microvolt = <4350000>;
|
||||
regulator-max-microvolt = <5800000>;
|
||||
regulator-min-microamp = <500000>;
|
||||
regulator-max-microamp = <3000000>;
|
||||
};
|
||||
};
|
||||
|
||||
indicator {
|
||||
compatible = "mediatek,mt6370-indicator";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
multi-led@0 {
|
||||
reg = <0>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
led-max-microamp = <24000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
led@0 {
|
||||
reg = <0>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
};
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
led@3 {
|
||||
reg = <3>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
led-max-microamp = <6000>;
|
||||
};
|
||||
};
|
||||
|
||||
flashlight {
|
||||
compatible = "mediatek,mt6370-flashlight";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
led@0 {
|
||||
reg = <0>;
|
||||
led-sources = <0>;
|
||||
function = LED_FUNCTION_FLASH;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function-enumerator = <1>;
|
||||
led-max-microamp = <200000>;
|
||||
flash-max-microamp = <500000>;
|
||||
flash-max-timeout-us = <1248000>;
|
||||
};
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
led-sources = <1>;
|
||||
function = LED_FUNCTION_FLASH;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
function-enumerator = <2>;
|
||||
led-max-microamp = <200000>;
|
||||
flash-max-microamp = <500000>;
|
||||
flash-max-timeout-us = <1248000>;
|
||||
};
|
||||
};
|
||||
|
||||
tcpc {
|
||||
compatible = "mediatek,mt6370-tcpc";
|
||||
interrupts-extended = <&gpio26 4 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
connector {
|
||||
compatible = "usb-c-connector";
|
||||
label = "USB-C";
|
||||
vbus-supply = <&mt6370_otg_vbus>;
|
||||
data-role = "dual";
|
||||
power-role = "dual";
|
||||
try-power-role = "sink";
|
||||
source-pdos = <PDO_FIXED(5000, 1000, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>;
|
||||
sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>;
|
||||
op-sink-microwatt = <10000000>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
endpoint {
|
||||
remote-endpoint = <&usb_hs>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
endpoint {
|
||||
remote-endpoint = <&usb_ss>;
|
||||
};
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
endpoint {
|
||||
remote-endpoint = <&dp_aux>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
regulators {
|
||||
dsvbst {
|
||||
regulator-name = "mt6370-dsv-vbst";
|
||||
regulator-min-microvolt = <4000000>;
|
||||
regulator-max-microvolt = <6200000>;
|
||||
};
|
||||
dsvpos {
|
||||
regulator-name = "mt6370-dsv-vpos";
|
||||
regulator-min-microvolt = <4000000>;
|
||||
regulator-max-microvolt = <6000000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
dsvneg {
|
||||
regulator-name = "mt6370-dsv-vneg";
|
||||
regulator-min-microvolt = <4000000>;
|
||||
regulator-max-microvolt = <6000000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
vibldo {
|
||||
regulator-name = "mt6370-vib-ldo";
|
||||
regulator-min-microvolt = <1600000>;
|
||||
regulator-max-microvolt = <4000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/mediatek,mt8195-scpsys.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek System Control Processor System
|
||||
|
||||
maintainers:
|
||||
- MandyJH Liu <mandyjh.liu@mediatek.com>
|
||||
|
||||
description:
|
||||
MediaTek System Control Processor System (SCPSYS) has several
|
||||
power management tasks. The tasks include MTCMOS power
|
||||
domain control, thermal measurement, DVFS, etc.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- mediatek,mt8167-scpsys
|
||||
- mediatek,mt8173-scpsys
|
||||
- mediatek,mt8183-scpsys
|
||||
- mediatek,mt8186-scpsys
|
||||
- mediatek,mt8192-scpsys
|
||||
- mediatek,mt8195-scpsys
|
||||
- const: syscon
|
||||
- const: simple-mfd
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
power-controller:
|
||||
$ref: /schemas/power/mediatek,power-controller.yaml#
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mt8195-clk.h>
|
||||
#include <dt-bindings/power/mt8195-power.h>
|
||||
|
||||
syscon@10006000 {
|
||||
compatible = "mediatek,mt8195-scpsys", "syscon", "simple-mfd";
|
||||
reg = <0x10006000 0x100>;
|
||||
|
||||
spm: power-controller {
|
||||
compatible = "mediatek,mt8195-power-controller";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#power-domain-cells = <1>;
|
||||
|
||||
/* sample of power domain nodes */
|
||||
power-domain@MT8195_POWER_DOMAIN_PCIE_PHY {
|
||||
reg = <MT8195_POWER_DOMAIN_PCIE_PHY>;
|
||||
#power-domain-cells = <0>;
|
||||
};
|
||||
|
||||
power-domain@MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY {
|
||||
reg = <MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY>;
|
||||
#power-domain-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -33,19 +33,22 @@ properties:
|
|||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,pm660
|
||||
- qcom,pm660l
|
||||
- qcom,pm6150
|
||||
- qcom,pm6150l
|
||||
- qcom,pm6350
|
||||
- qcom,pm660
|
||||
- qcom,pm660l
|
||||
- qcom,pm7250b
|
||||
- qcom,pm7325
|
||||
- qcom,pm8004
|
||||
- qcom,pm8005
|
||||
- qcom,pm8009
|
||||
- qcom,pm8019
|
||||
- qcom,pm8028
|
||||
- qcom,pm8110
|
||||
- qcom,pm8150
|
||||
- qcom,pm8150b
|
||||
- qcom,pm8150c
|
||||
- qcom,pm8150l
|
||||
- qcom,pm8226
|
||||
- qcom,pm8350
|
||||
|
|
@ -56,6 +59,7 @@ properties:
|
|||
- qcom,pm8916
|
||||
- qcom,pm8941
|
||||
- qcom,pm8950
|
||||
- qcom,pm8953
|
||||
- qcom,pm8994
|
||||
- qcom,pm8998
|
||||
- qcom,pma8084
|
||||
|
|
@ -64,8 +68,10 @@ properties:
|
|||
- qcom,pmi8962
|
||||
- qcom,pmi8994
|
||||
- qcom,pmi8998
|
||||
- qcom,pmk8002
|
||||
- qcom,pmk8350
|
||||
- qcom,pmm8155au
|
||||
- qcom,pmp8074
|
||||
- qcom,pmr735a
|
||||
- qcom,pmr735b
|
||||
- qcom,pms405
|
||||
|
|
@ -90,7 +96,7 @@ properties:
|
|||
|
||||
regulators:
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
$ref: /schemas/regulator/qcom,spmi-regulator.yaml#
|
||||
|
||||
patternProperties:
|
||||
"^adc@[0-9a-f]+$":
|
||||
|
|
@ -99,7 +105,7 @@ patternProperties:
|
|||
|
||||
"^adc-tm@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: /schemas/thermal/qcom-spmi-adc-tm5.yaml#
|
||||
# ref depends on compatible, see allOf below
|
||||
|
||||
"^audio-codec@[0-9a-f]+$":
|
||||
type: object
|
||||
|
|
@ -146,6 +152,22 @@ required:
|
|||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,pm8998
|
||||
then:
|
||||
patternProperties:
|
||||
"^adc-tm@[0-9a-f]+$":
|
||||
$ref: /schemas/thermal/qcom-spmi-adc-tm-hc.yaml#
|
||||
else:
|
||||
patternProperties:
|
||||
"^adc-tm@[0-9a-f]+$":
|
||||
$ref: /schemas/thermal/qcom-spmi-adc-tm5.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
|
@ -188,3 +210,87 @@ examples:
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/iio/qcom,spmi-vadc.h>
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
|
||||
pmic@0 {
|
||||
compatible = "qcom,pm6150", "qcom,spmi-pmic";
|
||||
reg = <0x0 SPMI_USID>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pon@800 {
|
||||
compatible = "qcom,pm8998-pon";
|
||||
reg = <0x800>;
|
||||
mode-bootloader = <0x2>;
|
||||
mode-recovery = <0x1>;
|
||||
|
||||
pwrkey {
|
||||
compatible = "qcom,pm8941-pwrkey";
|
||||
interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
|
||||
debounce = <15625>;
|
||||
bias-pull-up;
|
||||
linux,code = <KEY_POWER>;
|
||||
};
|
||||
};
|
||||
|
||||
temp-alarm@2400 {
|
||||
compatible = "qcom,spmi-temp-alarm";
|
||||
reg = <0x2400>;
|
||||
interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
|
||||
io-channels = <&pm6150_adc ADC5_DIE_TEMP>;
|
||||
io-channel-names = "thermal";
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
pm6150_adc: adc@3100 {
|
||||
compatible = "qcom,spmi-adc5";
|
||||
reg = <0x3100>;
|
||||
interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#io-channel-cells = <1>;
|
||||
|
||||
adc-chan@6 {
|
||||
reg = <ADC5_DIE_TEMP>;
|
||||
label = "die_temp";
|
||||
};
|
||||
|
||||
adc-chan@4f {
|
||||
reg = <ADC5_AMUX_THM3_100K_PU>;
|
||||
qcom,ratiometric;
|
||||
qcom,hw-settle-time = <200>;
|
||||
};
|
||||
};
|
||||
|
||||
adc-tm@3500 {
|
||||
compatible = "qcom,spmi-adc-tm5";
|
||||
reg = <0x3500>;
|
||||
interrupts = <0x0 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
charger-thermistor@0 {
|
||||
reg = <0>;
|
||||
io-channels = <&pm6150_adc ADC5_AMUX_THM3_100K_PU>;
|
||||
qcom,ratiometric;
|
||||
qcom,hw-settle-time-us = <200>;
|
||||
};
|
||||
};
|
||||
|
||||
pm6150_gpio: gpios@c000 {
|
||||
compatible = "qcom,pm6150-gpio", "qcom,spmi-gpio";
|
||||
reg = <0xc000>;
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pm6150_gpio 0 0 10>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,31 +15,27 @@ description:
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,msm8998-tcsr
|
||||
- qcom,qcs404-tcsr
|
||||
- qcom,sc7180-tcsr
|
||||
- qcom,sc7280-tcsr
|
||||
- qcom,sdm630-tcsr
|
||||
- qcom,sdm845-tcsr
|
||||
- qcom,sm8150-tcsr
|
||||
- qcom,tcsr-apq8064
|
||||
- qcom,tcsr-apq8084
|
||||
- qcom,tcsr-ipq8064
|
||||
- qcom,tcsr-mdm9615
|
||||
- qcom,tcsr-msm8660
|
||||
- qcom,tcsr-msm8916
|
||||
- qcom,tcsr-msm8953
|
||||
- qcom,tcsr-msm8960
|
||||
- qcom,tcsr-msm8974
|
||||
- qcom,tcsr-msm8996
|
||||
- const: syscon
|
||||
- items:
|
||||
- const: qcom,tcsr-ipq6018
|
||||
- const: syscon
|
||||
- const: simple-mfd
|
||||
items:
|
||||
- enum:
|
||||
- qcom,msm8998-tcsr
|
||||
- qcom,qcs404-tcsr
|
||||
- qcom,sc7180-tcsr
|
||||
- qcom,sc7280-tcsr
|
||||
- qcom,sdm630-tcsr
|
||||
- qcom,sdm845-tcsr
|
||||
- qcom,sm8150-tcsr
|
||||
- qcom,tcsr-apq8064
|
||||
- qcom,tcsr-apq8084
|
||||
- qcom,tcsr-ipq6018
|
||||
- qcom,tcsr-ipq8064
|
||||
- qcom,tcsr-mdm9615
|
||||
- qcom,tcsr-msm8660
|
||||
- qcom,tcsr-msm8916
|
||||
- qcom,tcsr-msm8953
|
||||
- qcom,tcsr-msm8960
|
||||
- qcom,tcsr-msm8974
|
||||
- qcom,tcsr-msm8996
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
|||
178
Documentation/devicetree/bindings/mfd/richtek,rt5120.yaml
Normal file
178
Documentation/devicetree/bindings/mfd/richtek,rt5120.yaml
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/richtek,rt5120.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Richtek RT5120 PMIC
|
||||
|
||||
maintainers:
|
||||
- ChiYuan Huang <cy_huang@richtek.com>
|
||||
|
||||
description: |
|
||||
The RT5120 provides four high-efficiency buck converters and one LDO voltage
|
||||
regulator. The device is targeted at providingthe processor voltage, memory,
|
||||
I/O, and peripheral rails in home entertainment devices. The I2C interface is
|
||||
used for dynamic voltage scaling of the processor voltage, power rails on/off
|
||||
sequence control, operation mode selection.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- richtek,rt5120
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 1
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
richtek,enable-undervolt-hiccup:
|
||||
type: boolean
|
||||
description: |
|
||||
If used, under voltage protection trigger hiccup behavior, else latchup as
|
||||
default
|
||||
|
||||
richtek,enable-overvolt-hiccup:
|
||||
type: boolean
|
||||
description:
|
||||
Like as 'enable-uv-hiccup', it configures over voltage protection to
|
||||
hiccup, else latchup as default
|
||||
|
||||
vin1-supply:
|
||||
description: phandle for buck1 input power source
|
||||
|
||||
vin2-supply:
|
||||
description: phandle for buck2 input power source
|
||||
|
||||
vin3-supply:
|
||||
description: phandle for buck3 input power source
|
||||
|
||||
vin4-supply:
|
||||
description: phandle for buck4 input power source
|
||||
|
||||
vinldo-supply:
|
||||
description: phandle for ldo input power source
|
||||
|
||||
regulators:
|
||||
type: object
|
||||
|
||||
patternProperties:
|
||||
"^buck[1-4]$":
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
regulator-allowed-modes:
|
||||
description: |
|
||||
Used to specify the allowed buck converter operating mode
|
||||
mode mapping:
|
||||
0: auto mode
|
||||
1: force pwm mode
|
||||
items:
|
||||
enum: [0, 1]
|
||||
|
||||
"^(ldo|exten)$":
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
powerkey:
|
||||
type: object
|
||||
description:
|
||||
PON key that connected to RT5120 PMIC.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- richtek,rt5120-pwrkey
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- '#interrupt-cells'
|
||||
- interrupt-controller
|
||||
- regulators
|
||||
- powerkey
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@62 {
|
||||
compatible = "richtek,rt5120";
|
||||
reg = <0x62>;
|
||||
interrupts-extended = <&gpio_intc 32 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
wakeup-source;
|
||||
|
||||
regulators {
|
||||
buck1 {
|
||||
regulator-name = "rt5120-buck1";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1393750>;
|
||||
regulator-allowed-modes = <0 1>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
buck2 {
|
||||
regulator-name = "rt5120-buck2";
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <1100000>;
|
||||
regulator-allowed-modes = <0 1>;
|
||||
regulator-always-on;
|
||||
};
|
||||
buck3 {
|
||||
regulator-name = "rt5120-buck3";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-allowed-modes = <0 1>;
|
||||
regulator-always-on;
|
||||
};
|
||||
buck4 {
|
||||
regulator-name = "rt5120-buck4";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-allowed-modes = <0 1>;
|
||||
regulator-always-on;
|
||||
};
|
||||
ldo {
|
||||
regulator-name = "rt5120-ldo";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
exten {
|
||||
regulator-name = "rt5120-exten";
|
||||
regulator-min-microvolt = <3000000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
powerkey {
|
||||
compatible = "richtek,rt5120-pwrkey";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -87,6 +87,7 @@ properties:
|
|||
patternProperties:
|
||||
"^(LDO_REG[1-9]|DCDC_REG[1-4]|BOOST|OTG_SWITCH)$":
|
||||
type: object
|
||||
unevaluatedProperties: false
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
|
@ -111,12 +112,56 @@ properties:
|
|||
additional properties are required for the codec, this node can be
|
||||
omitted.
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
rockchip,mic-in-differential:
|
||||
type: boolean
|
||||
description:
|
||||
Describes if the microphone uses differential mode.
|
||||
|
||||
charger:
|
||||
description: |
|
||||
The child node for the charger to hold additional properties. If a
|
||||
battery is not in use, this node can be omitted.
|
||||
type: object
|
||||
properties:
|
||||
monitored-battery:
|
||||
description: |
|
||||
A phandle to a monitored battery node that contains a valid
|
||||
value for:
|
||||
charge-full-design-microamp-hours,
|
||||
charge-term-current-microamp,
|
||||
constant-charge-current-max-microamp,
|
||||
constant-charge-voltage-max-microvolt,
|
||||
voltage-max-design-microvolt,
|
||||
voltage-min-design-microvolt,
|
||||
and a valid ocv-capacity table.
|
||||
|
||||
rockchip,resistor-sense-micro-ohms:
|
||||
description: |
|
||||
Value in microohms of the battery sense resistor. This value is
|
||||
used by the driver to set the correct divisor value to translate
|
||||
ADC readings into the proper units of measure.
|
||||
enum: [10000, 20000]
|
||||
|
||||
rockchip,sleep-enter-current-microamp:
|
||||
description: |
|
||||
Value in microamps of the sleep enter current for the charger.
|
||||
Value is used by the driver to calibrate the relax threshold.
|
||||
|
||||
rockchip,sleep-filter-current-microamp:
|
||||
description:
|
||||
Value in microamps of the sleep filter current for the charger.
|
||||
Value is used by the driver to derive the sleep sample current.
|
||||
|
||||
required:
|
||||
- monitored-battery
|
||||
- rockchip,resistor-sense-micro-ohms
|
||||
- rockchip,sleep-enter-current-microamp
|
||||
- rockchip,sleep-filter-current-microamp
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
|
|
@ -323,6 +368,13 @@ examples:
|
|||
};
|
||||
};
|
||||
|
||||
rk817_charger: charger {
|
||||
monitored-battery = <&battery>;
|
||||
rockchip,resistor-sense-micro-ohms = <10000>;
|
||||
rockchip,sleep-enter-current-microamp = <300000>;
|
||||
rockchip,sleep-filter-current-microamp = <100000>;
|
||||
};
|
||||
|
||||
rk817_codec: codec {
|
||||
rockchip,mic-in-differential;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ properties:
|
|||
vcom:
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
The regulator for the compenstation voltage. Enabling/disabling this
|
||||
enables/disables the entire device.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright 2022 Unisoc Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/sprd,ums512-glbreg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Unisoc System Global Register
|
||||
|
||||
maintainers:
|
||||
- Orson Zhai <orsonzhai@gmail.com>
|
||||
- Baolin Wang <baolin.wang7@gmail.com>
|
||||
- Chunyan Zhang <zhang.lyra@gmail.com>
|
||||
|
||||
description:
|
||||
Unisoc system global registers provide register map
|
||||
for clocks and some multimedia modules of the SoC.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: sprd,ums512-glbregs
|
||||
- const: syscon
|
||||
- const: simple-mfd
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
ranges:
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^clock-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: /schemas/clock/sprd,ums512-clk.yaml#
|
||||
description:
|
||||
Clock controller for the SoC clocks.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
ap_apb_regs: syscon@71000000 {
|
||||
compatible = "sprd,ums512-glbregs", "syscon", "simple-mfd";
|
||||
reg = <0x71000000 0x3000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x71000000 0x3000>;
|
||||
|
||||
clock-controller@0 {
|
||||
compatible = "sprd,ums512-apahb-gate";
|
||||
reg = <0x0 0x2000>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
ap_intc5_regs: syscon@32360000 {
|
||||
compatible = "sprd,ums512-glbregs", "syscon", "simple-mfd";
|
||||
reg = <0x32360000 0x1000>;
|
||||
};
|
||||
|
|
@ -46,6 +46,7 @@ properties:
|
|||
|
||||
pwm:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -60,6 +61,7 @@ properties:
|
|||
|
||||
counter:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -70,6 +72,7 @@ properties:
|
|||
|
||||
timer:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -81,6 +84,7 @@ properties:
|
|||
patternProperties:
|
||||
"^trigger@[0-9]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ properties:
|
|||
|
||||
pwm:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -104,6 +105,7 @@ properties:
|
|||
|
||||
counter:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -115,6 +117,7 @@ properties:
|
|||
patternProperties:
|
||||
"^timer@[0-9]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ properties:
|
|||
patternProperties:
|
||||
"^[a-zA-Z]*-pins$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: ../pinctrl/pinmux-node.yaml
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ properties:
|
|||
provides the reference clock for the entire U8500 system and
|
||||
the DB8500 counterpart.
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -63,6 +64,7 @@ properties:
|
|||
description: Node describing the AB8500 GPIO controller. A few
|
||||
GPIO pins available for misc usage.
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -78,6 +80,7 @@ properties:
|
|||
rtc:
|
||||
description: Node describing the AB8500 battery-backed RTC.
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -337,34 +340,40 @@ properties:
|
|||
description: The voltage for the auxilary LDO regulator 1
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_aux2:
|
||||
description: The voltage for the auxilary LDO regulator 2
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_aux3:
|
||||
description: The voltage for the auxilary LDO regulator 3
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_aux4:
|
||||
description: The voltage for the auxilary LDO regulator 4
|
||||
only present on AB8505
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_aux5:
|
||||
description: The voltage for the auxilary LDO regulator 5
|
||||
only present on AB8505
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_aux6:
|
||||
description: The voltage for the auxilary LDO regulator 6
|
||||
only present on AB8505
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
# There is never any AUX7 regulator which is confusing
|
||||
|
||||
|
|
@ -373,18 +382,21 @@ properties:
|
|||
only present on AB8505
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_intcore:
|
||||
description: The LDO regulator for the internal core voltage
|
||||
of the AB8500
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_adc:
|
||||
description: Analog power regulator for the analog to digital converter
|
||||
ADC, only present on AB8505
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_tvout:
|
||||
description: The voltage for the TV output regulator, incidentally
|
||||
|
|
@ -393,33 +405,39 @@ properties:
|
|||
Only present on AB8500.
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_audio:
|
||||
description: The LDO regulator for the audio codec output
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_anamic1:
|
||||
description: The LDO regulator for the analog microphone 1
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_anamic2:
|
||||
description: The LDO regulator for the analog microphone 2
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_dmic:
|
||||
description: The LDO regulator for the digital microphone
|
||||
only present on AB8500
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ldo_ana:
|
||||
description: Analog power regulator for CSI and DSI interfaces,
|
||||
Camera Serial Interface CSI and Display Serial Interface DSI.
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
@ -442,16 +460,19 @@ properties:
|
|||
description: The voltage for the VSMPS1 external regulator
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ext2:
|
||||
description: The voltage for the VSMPS2 external regulator
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
ab8500_ext3:
|
||||
description: The voltage for the VSMPS3 external regulator
|
||||
type: object
|
||||
$ref: ../regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
@ -462,6 +483,7 @@ patternProperties:
|
|||
"^pwm@[1-9]+?$":
|
||||
type: object
|
||||
$ref: ../pwm/pwm.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: Represents each of the PWM blocks in the AB8500
|
||||
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ properties:
|
|||
- rockchip,rk3368-qos
|
||||
- rockchip,rk3399-qos
|
||||
- rockchip,rk3568-qos
|
||||
- rockchip,rk3588-qos
|
||||
- rockchip,rv1126-qos
|
||||
- samsung,exynos3-sysreg
|
||||
- samsung,exynos4-sysreg
|
||||
- samsung,exynos5-sysreg
|
||||
|
|
@ -73,7 +75,7 @@ properties:
|
|||
- contains:
|
||||
const: syscon
|
||||
minItems: 2
|
||||
maxItems: 4 # Should be enough
|
||||
maxItems: 5 # Should be enough
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
@ -82,7 +84,6 @@ properties:
|
|||
description: |
|
||||
The size (in bytes) of the IO accesses that should be performed
|
||||
on the device.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [1, 2, 4, 8]
|
||||
|
||||
hwlocks:
|
||||
|
|
@ -94,6 +95,18 @@ required:
|
|||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: simple-mfd
|
||||
then:
|
||||
properties:
|
||||
compatible:
|
||||
minItems: 3
|
||||
maxItems: 5
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
examples:
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ properties:
|
|||
|
||||
regulators:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: |
|
||||
List of child nodes that specify the regulator initialization data.
|
||||
Child nodes must be named after their hardware counterparts:
|
||||
|
|
|
|||
|
|
@ -92,6 +92,9 @@ properties:
|
|||
- x-powers,axp806
|
||||
- x-powers,axp809
|
||||
- x-powers,axp813
|
||||
- items:
|
||||
- const: x-powers,axp228
|
||||
- const: x-powers,axp221
|
||||
- items:
|
||||
- const: x-powers,axp805
|
||||
- const: x-powers,axp806
|
||||
|
|
@ -260,6 +263,7 @@ properties:
|
|||
"^(([a-f])?ldo[0-9]|dcdc[0-7a-e]|ldo(_|-)io(0|1)|(dc1)?sw|rtc(_|-)ldo|drivevbus|dc5ldo)$":
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
type: object
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
regulator-ramp-delay:
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
Amlogic NAND Flash Controller (NFC) for GXBB/GXL/AXG family SoCs
|
||||
|
||||
This file documents the properties in addition to those available in
|
||||
the MTD NAND bindings.
|
||||
|
||||
Required properties:
|
||||
- compatible : contains one of:
|
||||
- "amlogic,meson-gxl-nfc"
|
||||
- "amlogic,meson-axg-nfc"
|
||||
- clocks :
|
||||
A list of phandle + clock-specifier pairs for the clocks listed
|
||||
in clock-names.
|
||||
|
||||
- clock-names: Should contain the following:
|
||||
"core" - NFC module gate clock
|
||||
"device" - device clock from eMMC sub clock controller
|
||||
"rx" - rx clock phase
|
||||
"tx" - tx clock phase
|
||||
|
||||
- amlogic,mmc-syscon : Required for NAND clocks, it's shared with SD/eMMC
|
||||
controller port C
|
||||
|
||||
Optional children nodes:
|
||||
Children nodes represent the available nand chips.
|
||||
|
||||
Other properties:
|
||||
see Documentation/devicetree/bindings/mtd/nand-controller.yaml for generic bindings.
|
||||
|
||||
Example demonstrate on AXG SoC:
|
||||
|
||||
sd_emmc_c_clkc: mmc@7000 {
|
||||
compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
|
||||
reg = <0x0 0x7000 0x0 0x800>;
|
||||
};
|
||||
|
||||
nand-controller@7800 {
|
||||
compatible = "amlogic,meson-axg-nfc";
|
||||
reg = <0x0 0x7800 0x0 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>;
|
||||
|
||||
clocks = <&clkc CLKID_SD_EMMC_C>,
|
||||
<&sd_emmc_c_clkc CLKID_MMC_DIV>,
|
||||
<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
|
||||
<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
|
||||
clock-names = "core", "device", "rx", "tx";
|
||||
amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&nand_pins>;
|
||||
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
nand-on-flash-bbt;
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mtd/amlogic,meson-nand.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic NAND Flash Controller (NFC) for GXBB/GXL/AXG family SoCs
|
||||
|
||||
allOf:
|
||||
- $ref: nand-controller.yaml
|
||||
|
||||
maintainers:
|
||||
- liang.yang@amlogic.com
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- amlogic,meson-gxl-nfc
|
||||
- amlogic,meson-axg-nfc
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: nfc
|
||||
- const: emmc
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: device
|
||||
|
||||
patternProperties:
|
||||
"^nand@[0-7]$":
|
||||
type: object
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
|
||||
nand-ecc-mode:
|
||||
const: hw
|
||||
|
||||
nand-ecc-step-size:
|
||||
const: 1024
|
||||
|
||||
nand-ecc-strength:
|
||||
enum: [8, 16, 24, 30, 40, 50, 60]
|
||||
description: |
|
||||
The ECC configurations that can be supported are as follows.
|
||||
meson-gxl-nfc 8, 16, 24, 30, 40, 50, 60
|
||||
meson-axg-nfc 8
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/axg-clkc.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
nand-controller@ffe07800 {
|
||||
compatible = "amlogic,meson-axg-nfc";
|
||||
reg = <0xffe07800 0x100>, <0xffe07000 0x800>;
|
||||
reg-names = "nfc", "emmc";
|
||||
interrupts = <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_FCLK_DIV2>;
|
||||
clock-names = "core", "device";
|
||||
|
||||
pinctrl-0 = <&nand_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mtd/intel,lgm-nand.yaml#
|
||||
$id: http://devicetree.org/schemas/mtd/intel,lgm-ebunand.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Intel LGM SoC NAND Controller Device Tree Bindings
|
||||
|
|
@ -14,7 +14,7 @@ maintainers:
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
const: intel,lgm-nand
|
||||
const: intel,lgm-ebunand
|
||||
|
||||
reg:
|
||||
maxItems: 6
|
||||
|
|
@ -51,7 +51,7 @@ patternProperties:
|
|||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
maximum: 1
|
||||
|
||||
nand-ecc-mode: true
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ additionalProperties: false
|
|||
examples:
|
||||
- |
|
||||
nand-controller@e0f00000 {
|
||||
compatible = "intel,lgm-nand";
|
||||
compatible = "intel,lgm-ebunand";
|
||||
reg = <0xe0f00000 0x100>,
|
||||
<0xe1000000 0x300>,
|
||||
<0xe1400000 0x8000>,
|
||||
49
Documentation/devicetree/bindings/mtd/partitions/u-boot.yaml
Normal file
49
Documentation/devicetree/bindings/mtd/partitions/u-boot.yaml
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mtd/partitions/u-boot.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: U-Boot bootloader partition
|
||||
|
||||
description: |
|
||||
U-Boot is a bootlodaer commonly used in embedded devices. It's almost always
|
||||
located on some kind of flash device.
|
||||
|
||||
Device configuration is stored as a set of environment variables that are
|
||||
located in a (usually standalone) block of data.
|
||||
|
||||
maintainers:
|
||||
- Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
allOf:
|
||||
- $ref: partition.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: brcm,u-boot
|
||||
description: |
|
||||
Broadcom stores environment variables inside a U-Boot partition. They
|
||||
can be identified by a custom header with magic value.
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
compatible = "brcm,u-boot";
|
||||
reg = <0x0 0x100000>;
|
||||
label = "u-boot";
|
||||
};
|
||||
|
||||
partition@100000 {
|
||||
reg = <0x100000 0x1ff00000>;
|
||||
label = "firmware";
|
||||
};
|
||||
};
|
||||
|
|
@ -135,7 +135,7 @@ examples:
|
|||
#size-cells = <2>;
|
||||
|
||||
scpsys: syscon@10006000 {
|
||||
compatible = "syscon", "simple-mfd";
|
||||
compatible = "mediatek,mt8173-scpsys", "syscon", "simple-mfd";
|
||||
reg = <0 0x10006000 0 0x1000>;
|
||||
|
||||
spm: power-controller {
|
||||
|
|
|
|||
|
|
@ -15,18 +15,27 @@ description: |
|
|||
|
||||
This DT node has pwrkey and resin as sub nodes.
|
||||
|
||||
allOf:
|
||||
- $ref: reboot-mode.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,pm8916-pon
|
||||
- qcom,pms405-pon
|
||||
- qcom,pm8998-pon
|
||||
- qcom,pmk8350-pon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: |
|
||||
Specifies the SPMI base address for the PON (power-on) peripheral. For
|
||||
PMICs that have the PON peripheral (GEN3) split into PON_HLOS and PON_PBS
|
||||
(e.g. PMK8350), this can hold addresses of both PON_HLOS and PON_PBS
|
||||
peripherals. In that case, the PON_PBS address needs to be specified to
|
||||
facilitate software debouncing on some PMIC.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
pwrkey:
|
||||
type: object
|
||||
|
|
@ -46,6 +55,39 @@ required:
|
|||
|
||||
unevaluatedProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: reboot-mode.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,pm8916-pon
|
||||
- qcom,pms405-pon
|
||||
- qcom,pm8998-pon
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
reg-names:
|
||||
items:
|
||||
- const: pon
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,pmk8350-pon
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
reg-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: hlos
|
||||
- const: pbs
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/power/supply/mediatek,mt6370-charger.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT6370 Battery Charger
|
||||
|
||||
maintainers:
|
||||
- ChiaEn Wu <chiaen_wu@richtek.com>
|
||||
|
||||
description: |
|
||||
This module is part of the MT6370 MFD device.
|
||||
Provides Battery Charger, Boost for OTG devices and BC1.2 detection.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6370-charger
|
||||
|
||||
interrupts:
|
||||
description: |
|
||||
Specify what irqs are needed to be handled by MT6370 Charger driver.
|
||||
We need to use the IRQ "MT6370_IRQ_OVPCTRL_UVP_D" to know when USB
|
||||
is plugged in, and then the driver will enable BC1.2 detection.
|
||||
After the hardware of MT6370 completes the BC1.2 detection,
|
||||
IRQ "MT6370_IRQ_ATTACH" will be triggered, and the driver will know
|
||||
the result of BC1.2 detection.
|
||||
When the IRQ "MT6370_IRQ_CHG_MIVR" is triggered, it means that the
|
||||
hardware enters the "Minimum Input Voltage Regulation loop" and
|
||||
a workaround needs to be applied at this time.
|
||||
In summary, "MT6370_IRQ_OVPCTRL_UVP_D", "MT6370_IRQ_ATTACH" and
|
||||
"MT6370_IRQ_CHG_MIVR" are required in this charger driver.
|
||||
items:
|
||||
- description: irq of "USB is plugged in"
|
||||
- description: irq of "BC1.2 is done"
|
||||
- description: irq of "Minimum Input Voltage Regulation loop is active"
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: uvp_d_evt
|
||||
- const: attach_i
|
||||
- const: mivr
|
||||
|
||||
io-channels:
|
||||
description: |
|
||||
Use ADC channel to read VBUS, IBUS, IBAT, etc., info.
|
||||
minItems: 1
|
||||
items:
|
||||
- description: |
|
||||
VBUS voltage with lower accuracy (+-75mV) but higher measure
|
||||
range (1~22V)
|
||||
- description: |
|
||||
VBUS voltage with higher accuracy (+-30mV) but lower measure
|
||||
range (1~9.76V)
|
||||
- description: the main system input voltage
|
||||
- description: battery voltage
|
||||
- description: battery temperature-sense input voltage
|
||||
- description: IBUS current (required)
|
||||
- description: battery current
|
||||
- description: |
|
||||
regulated output voltage to supply for the PWM low-side gate driver
|
||||
and the bootstrap capacitor
|
||||
- description: IC junction temperature
|
||||
|
||||
io-channel-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: vbusdiv5
|
||||
- const: vbusdiv2
|
||||
- const: vsys
|
||||
- const: vbat
|
||||
- const: ts_bat
|
||||
- const: ibus
|
||||
- const: ibat
|
||||
- const: chg_vddp
|
||||
- const: temp_jc
|
||||
|
||||
usb-otg-vbus-regulator:
|
||||
type: object
|
||||
description: OTG boost regulator.
|
||||
unevaluatedProperties: false
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
|
||||
properties:
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- io-channels
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
...
|
||||
|
|
@ -27,6 +27,7 @@ properties:
|
|||
- items:
|
||||
- enum:
|
||||
- mediatek,mt8186-disp-pwm
|
||||
- mediatek,mt8188-disp-pwm
|
||||
- mediatek,mt8192-disp-pwm
|
||||
- mediatek,mt8195-disp-pwm
|
||||
- const: mediatek,mt8183-disp-pwm
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ properties:
|
|||
- const: rockchip,rk2928-pwm
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rk3128-pwm
|
||||
- rockchip,rk3368-pwm
|
||||
- rockchip,rk3399-pwm
|
||||
- rockchip,rv1108-pwm
|
||||
|
|
@ -30,6 +31,7 @@ properties:
|
|||
- rockchip,px30-pwm
|
||||
- rockchip,rk3308-pwm
|
||||
- rockchip,rk3568-pwm
|
||||
- rockchip,rk3588-pwm
|
||||
- const: rockchip,rk3328-pwm
|
||||
|
||||
reg:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/mediatek/mediatek,ccorr.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek color correction
|
||||
|
||||
maintainers:
|
||||
- Matthias Brugger <matthias.bgg@gmail.com>
|
||||
- Moudy Ho <moudy.ho@mediatek.com>
|
||||
|
||||
description: |
|
||||
MediaTek color correction with 3X3 matrix.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- mediatek,mt8183-mdp3-ccorr
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
mediatek,gce-client-reg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
items:
|
||||
items:
|
||||
- description: phandle of GCE
|
||||
- description: GCE subsys id
|
||||
- description: register offset
|
||||
- description: register size
|
||||
description: The register of client driver can be configured by gce with
|
||||
4 arguments defined in this property. Each GCE subsys id is mapping to
|
||||
a client defined in the header include/dt-bindings/gce/<chip>-gce.h.
|
||||
|
||||
mediatek,gce-events:
|
||||
description:
|
||||
The event id which is mapping to the specific hardware event signal
|
||||
to gce. The event id is defined in the gce header
|
||||
include/dt-bindings/gce/<chip>-gce.h of each chips.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- mediatek,gce-client-reg
|
||||
- mediatek,gce-events
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mt8183-clk.h>
|
||||
#include <dt-bindings/gce/mt8183-gce.h>
|
||||
|
||||
mdp3_ccorr: mdp3-ccorr@1401c000 {
|
||||
compatible = "mediatek,mt8183-mdp3-ccorr";
|
||||
reg = <0x1401c000 0x1000>;
|
||||
mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0xc000 0x1000>;
|
||||
mediatek,gce-events = <CMDQ_EVENT_MDP_CCORR_SOF>,
|
||||
<CMDQ_EVENT_MDP_CCORR_EOF>;
|
||||
clocks = <&mmsys CLK_MM_MDP_CCORR>;
|
||||
};
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/mediatek/mediatek,wdma.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek Write Direct Memory Access
|
||||
|
||||
maintainers:
|
||||
- Matthias Brugger <matthias.bgg@gmail.com>
|
||||
- Moudy Ho <moudy.ho@mediatek.com>
|
||||
|
||||
description: |
|
||||
MediaTek Write Direct Memory Access(WDMA) component used to write
|
||||
the data into DMA.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- mediatek,mt8183-mdp3-wdma
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
mediatek,gce-client-reg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
items:
|
||||
items:
|
||||
- description: phandle of GCE
|
||||
- description: GCE subsys id
|
||||
- description: register offset
|
||||
- description: register size
|
||||
description: The register of client driver can be configured by gce with
|
||||
4 arguments defined in this property. Each GCE subsys id is mapping to
|
||||
a client defined in the header include/dt-bindings/gce/<chip>-gce.h.
|
||||
|
||||
mediatek,gce-events:
|
||||
description:
|
||||
The event id which is mapping to the specific hardware event signal
|
||||
to gce. The event id is defined in the gce header
|
||||
include/dt-bindings/gce/<chip>-gce.h of each chips.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- mediatek,gce-client-reg
|
||||
- mediatek,gce-events
|
||||
- power-domains
|
||||
- clocks
|
||||
- iommus
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mt8183-clk.h>
|
||||
#include <dt-bindings/gce/mt8183-gce.h>
|
||||
#include <dt-bindings/power/mt8183-power.h>
|
||||
#include <dt-bindings/memory/mt8183-larb-port.h>
|
||||
|
||||
mdp3_wdma: mdp3-wdma@14006000 {
|
||||
compatible = "mediatek,mt8183-mdp3-wdma";
|
||||
reg = <0x14006000 0x1000>;
|
||||
mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x6000 0x1000>;
|
||||
mediatek,gce-events = <CMDQ_EVENT_MDP_WDMA0_SOF>,
|
||||
<CMDQ_EVENT_MDP_WDMA0_EOF>;
|
||||
power-domains = <&spm MT8183_POWER_DOMAIN_DISP>;
|
||||
clocks = <&mmsys CLK_MM_MDP_WDMA0>;
|
||||
iommus = <&iommu>;
|
||||
};
|
||||
|
|
@ -19,7 +19,7 @@ Global video workflow
|
|||
|
||||
a) QCI stopped
|
||||
Initially, the QCI interface is stopped.
|
||||
When a buffer is queued (pxa_videobuf_ops->buf_queue), the QCI starts.
|
||||
When a buffer is queued, start_streaming is called and the QCI starts.
|
||||
|
||||
b) QCI started
|
||||
More buffers can be queued while the QCI is started without halting the
|
||||
|
|
|
|||
84
Documentation/userspace-api/media/drivers/dw100.rst
Normal file
84
Documentation/userspace-api/media/drivers/dw100.rst
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
DW100 dewarp driver
|
||||
===================
|
||||
|
||||
The Vivante DW100 Dewarp Processor IP core found on i.MX8MP SoC applies a
|
||||
programmable geometrical transformation on the input image to correct distortion
|
||||
introduced by lenses.
|
||||
|
||||
The transformation function is exposed by the hardware as a grid map with 16x16
|
||||
pixel macroblocks indexed using X, Y vertex coordinates.
|
||||
::
|
||||
|
||||
Image width
|
||||
<--------------------------------------->
|
||||
|
||||
^ .-------.-------.-------.-------.-------.
|
||||
| | 16x16 | | | | |
|
||||
I | | pixel | | | | |
|
||||
m | | block | | | | |
|
||||
a | .-------.-------.-------.-------.-------.
|
||||
g | | | | | | |
|
||||
e | | | | | | |
|
||||
| | | | | | |
|
||||
h | .-------.-------.-------.-------.-------.
|
||||
e | | | | | | |
|
||||
i | | | | | | |
|
||||
g | | | | | | |
|
||||
h | .-------.-------.-------.-------.-------.
|
||||
t | | | | | | |
|
||||
| | | | | | |
|
||||
| | | | | | |
|
||||
v '-------'-------'-------'-------'-------'
|
||||
|
||||
Grid of Image Blocks for Dewarping Map
|
||||
|
||||
|
||||
Each x, y coordinate register uses 16 bits to record the coordinate address in
|
||||
an unsigned 12.4 fixed point format (UQ12.4).
|
||||
::
|
||||
|
||||
.----------------------.--------..----------------------.--------.
|
||||
| 31~20 | 19~16 || 15~4 | 3~0 |
|
||||
| (integer) | (frac) || (integer) | (frac) |
|
||||
'----------------------'--------''----------------------'--------'
|
||||
<-------------------------------><------------------------------->
|
||||
Y coordinate X coordinate
|
||||
|
||||
Remap Register Layout
|
||||
|
||||
The dewarping map is set from applications using the
|
||||
V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP control. The control contains
|
||||
an array of u32 values storing (x, y) destination coordinates for each
|
||||
vertex of the grid. The x coordinate is stored in the 16 LSBs and the y
|
||||
coordinate in the 16 MSBs.
|
||||
|
||||
The number of elements in the array must match the image size:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
elems = (DIV_ROUND_UP(width, 16) + 1) * (DIV_ROUND_UP(height, 16) + 1);
|
||||
|
||||
If the control has not been set by the application, the driver uses an identity
|
||||
map.
|
||||
|
||||
More details on the DW100 hardware operations can be found in
|
||||
*chapter 13.15 DeWarp* of IMX8MP_ reference manual.
|
||||
|
||||
The Vivante DW100 m2m driver implements the following driver-specific control:
|
||||
|
||||
``V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP (__u32 array)``
|
||||
Specifies to DW100 driver its dewarping map (aka LUT) blob as described in
|
||||
*chapter 13.15.2.3 Dewarping Remap* of IMX8MP_ reference manual as an U32
|
||||
dynamic array. The image is divided into many small 16x16 blocks. If the
|
||||
width/height of the image is not divisible by 16, the size of the
|
||||
rightmost/bottommost block is the remainder. The dewarping map only saves
|
||||
the vertex coordinates of the block. The dewarping grid map is comprised of
|
||||
vertex coordinates for x and y. Each x, y coordinate register uses 16 bits
|
||||
(UQ12.4) to record the coordinate address, with the Y coordinate in the
|
||||
upper bits and X in the lower bits. The driver modifies the dimensions of
|
||||
this control when the sink format is changed, to reflect the new input
|
||||
resolution.
|
||||
|
||||
.. _IMX8MP: https://www.nxp.com/webapp/Download?colCode=IMX8MPRM
|
||||
|
|
@ -33,6 +33,7 @@ For more details see the file COPYING in the source distribution of Linux.
|
|||
|
||||
ccs
|
||||
cx2341x-uapi
|
||||
dw100
|
||||
imx-uapi
|
||||
max2175
|
||||
meye-uapi
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
|
||||
|
||||
.. _async:
|
||||
|
||||
****************
|
||||
Asynchronous I/O
|
||||
****************
|
||||
|
||||
This method is not defined yet.
|
||||
|
|
@ -41,7 +41,7 @@ Devices supporting the raw VBI capturing or output API set the
|
|||
in the ``capabilities`` field of struct
|
||||
:c:type:`v4l2_capability` returned by the
|
||||
:ref:`VIDIOC_QUERYCAP` ioctl. At least one of the
|
||||
read/write, streaming or asynchronous I/O methods must be supported. VBI
|
||||
read/write or streaming I/O methods must be supported. VBI
|
||||
devices may or may not have a tuner or modulator.
|
||||
|
||||
Supplemental Functions
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ Devices supporting the SDR transmitter interface set the
|
|||
device has an Digital to Analog Converter (DAC), which is a mandatory
|
||||
element for the SDR transmitter.
|
||||
|
||||
At least one of the read/write, streaming or asynchronous I/O methods
|
||||
At least one of the read/write or streaming I/O methods
|
||||
must be supported.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Devices supporting the sliced VBI capturing or output API set the
|
|||
respectively, in the ``capabilities`` field of struct
|
||||
:c:type:`v4l2_capability` returned by the
|
||||
:ref:`VIDIOC_QUERYCAP` ioctl. At least one of the
|
||||
read/write, streaming or asynchronous :ref:`I/O methods <io>` must be
|
||||
read/write or streaming :ref:`I/O methods <io>` must be
|
||||
supported. Sliced VBI devices may have a tuner or modulator.
|
||||
|
||||
Supplemental Functions
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ This unnamed version was finally merged into Linux 2.5.46.
|
|||
There are new fields to identify the driver, a new RDS device
|
||||
function ``V4L2_CAP_RDS_CAPTURE``, the ``V4L2_CAP_AUDIO`` flag
|
||||
indicates if the device has any audio connectors, another I/O
|
||||
capability ``V4L2_CAP_ASYNCIO`` can be flagged. In response to these
|
||||
capability V4L2_CAP_ASYNCIO can be flagged. In response to these
|
||||
changes the ``type`` field became a bit set and was merged into the
|
||||
``flags`` field. ``V4L2_FLAG_TUNER`` was renamed to
|
||||
``V4L2_CAP_TUNER``, ``V4L2_CAP_VIDEO_OVERLAY`` replaced
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ read or write will fail at any time.
|
|||
|
||||
Other methods must be negotiated. To select the streaming I/O method
|
||||
with memory mapped or user buffers applications call the
|
||||
:ref:`VIDIOC_REQBUFS` ioctl. The asynchronous I/O
|
||||
method is not defined yet.
|
||||
:ref:`VIDIOC_REQBUFS` ioctl.
|
||||
|
||||
Video overlay can be considered another I/O method, although the
|
||||
application does not directly receive the image data. It is selected by
|
||||
|
|
@ -46,6 +45,5 @@ The following sections describe the various I/O methods in more detail.
|
|||
mmap
|
||||
userp
|
||||
dmabuf
|
||||
async
|
||||
buffer
|
||||
field-order
|
||||
|
|
|
|||
|
|
@ -332,6 +332,11 @@ call.
|
|||
- 0x0004
|
||||
- This control event was triggered because the minimum, maximum,
|
||||
step or the default value of the control changed.
|
||||
* - ``V4L2_EVENT_CTRL_CH_DIMENSIONS``
|
||||
- 0x0008
|
||||
- This control event was triggered because the dimensions of the
|
||||
control changed. Note that the number of dimensions remains the
|
||||
same.
|
||||
|
||||
|
||||
.. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.5cm}|
|
||||
|
|
|
|||
|
|
@ -244,9 +244,6 @@ specification the ioctl returns an ``EINVAL`` error code.
|
|||
- 0x01000000
|
||||
- The device supports the :c:func:`read()` and/or
|
||||
:c:func:`write()` I/O methods.
|
||||
* - ``V4L2_CAP_ASYNCIO``
|
||||
- 0x02000000
|
||||
- The device supports the :ref:`asynchronous <async>` I/O methods.
|
||||
* - ``V4L2_CAP_STREAMING``
|
||||
- 0x04000000
|
||||
- The device supports the :ref:`streaming <mmap>` I/O method.
|
||||
|
|
|
|||
|
|
@ -514,6 +514,7 @@ replace define V4L2_EVENT_PRIVATE_START event-type
|
|||
replace define V4L2_EVENT_CTRL_CH_VALUE ctrl-changes-flags
|
||||
replace define V4L2_EVENT_CTRL_CH_FLAGS ctrl-changes-flags
|
||||
replace define V4L2_EVENT_CTRL_CH_RANGE ctrl-changes-flags
|
||||
replace define V4L2_EVENT_CTRL_CH_DIMENSIONS ctrl-changes-flags
|
||||
|
||||
replace define V4L2_EVENT_SRC_CH_RESOLUTION src-changes-flags
|
||||
|
||||
|
|
|
|||
55
MAINTAINERS
55
MAINTAINERS
|
|
@ -8475,7 +8475,6 @@ F: tools/testing/selftests/futex/
|
|||
|
||||
GATEWORKS SYSTEM CONTROLLER (GSC) DRIVER
|
||||
M: Tim Harvey <tharvey@gateworks.com>
|
||||
M: Robert Jones <rjones@gateworks.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml
|
||||
F: drivers/mfd/gateworks-gsc.c
|
||||
|
|
@ -8936,7 +8935,7 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/media/nxp,imx8mq-vpu.yaml
|
||||
F: Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml
|
||||
F: Documentation/devicetree/bindings/media/rockchip-vpu.yaml
|
||||
F: drivers/staging/media/hantro/
|
||||
F: drivers/media/platform/verisilicon/
|
||||
|
||||
HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
|
||||
M: Frank Seidel <frank@f-seidel.de>
|
||||
|
|
@ -9082,6 +9081,12 @@ L: linux-input@vger.kernel.org
|
|||
S: Supported
|
||||
F: drivers/hid/hid-playstation.c
|
||||
|
||||
HID PHOENIX RC FLIGHT CONTROLLER
|
||||
M: Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hid/hid-pxrc.c
|
||||
|
||||
HID SENSOR HUB DRIVERS
|
||||
M: Jiri Kosina <jikos@kernel.org>
|
||||
M: Jonathan Cameron <jic23@kernel.org>
|
||||
|
|
@ -9094,6 +9099,12 @@ F: drivers/hid/hid-sensor-*
|
|||
F: drivers/iio/*/hid-*
|
||||
F: include/linux/hid-sensor-*
|
||||
|
||||
HID VRC-2 CAR CONTROLLER DRIVER
|
||||
M: Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hid/hid-vrc2.c
|
||||
|
||||
HID WACOM DRIVER
|
||||
M: Ping Cheng <ping.cheng@wacom.com>
|
||||
M: Jason Gerecke <jason.gerecke@wacom.com>
|
||||
|
|
@ -11591,6 +11602,15 @@ F: drivers/ata/ahci_platform.c
|
|||
F: drivers/ata/libahci_platform.c
|
||||
F: include/linux/ahci_platform.h
|
||||
|
||||
LIBATA SATA AHCI SYNOPSYS DWC CONTROLLER DRIVER
|
||||
M: Serge Semin <fancer.lancer@gmail.com>
|
||||
L: linux-ide@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata.git
|
||||
F: Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
|
||||
F: Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
|
||||
F: drivers/ata/ahci_dwc.c
|
||||
|
||||
LIBATA SATA PROMISE TX2/TX4 CONTROLLER DRIVER
|
||||
M: Mikael Pettersson <mikpelinux@gmail.com>
|
||||
L: linux-ide@vger.kernel.org
|
||||
|
|
@ -13821,7 +13841,7 @@ MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
|
|||
S: Orphan
|
||||
W: http://popies.net/meye/
|
||||
F: Documentation/userspace-api/media/drivers/meye*
|
||||
F: drivers/media/pci/meye/
|
||||
F: drivers/staging/media/deprecated/meye/
|
||||
F: include/uapi/linux/meye.h
|
||||
|
||||
MOTORCOMM PHY DRIVER
|
||||
|
|
@ -14589,6 +14609,15 @@ F: drivers/nvme/common/
|
|||
F: include/linux/nvme*
|
||||
F: include/uapi/linux/nvme_ioctl.h
|
||||
|
||||
NVM EXPRESS FABRICS AUTHENTICATION
|
||||
M: Hannes Reinecke <hare@suse.de>
|
||||
L: linux-nvme@lists.infradead.org
|
||||
S: Supported
|
||||
F: drivers/nvme/host/auth.c
|
||||
F: drivers/nvme/target/auth.c
|
||||
F: drivers/nvme/target/fabrics-cmd-auth.c
|
||||
F: include/linux/nvme-auth.h
|
||||
|
||||
NVM EXPRESS FC TRANSPORT DRIVERS
|
||||
M: James Smart <james.smart@broadcom.com>
|
||||
L: linux-nvme@lists.infradead.org
|
||||
|
|
@ -14738,6 +14767,15 @@ S: Orphan
|
|||
F: Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml
|
||||
F: drivers/nfc/nxp-nci
|
||||
|
||||
NXP i.MX 8MP DW100 V4L2 DRIVER
|
||||
M: Xavier Roumegue <xavier.roumegue@oss.nxp.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/media/nxp,dw100.yaml
|
||||
F: Documentation/userspace-api/media/drivers/dw100.rst
|
||||
F: drivers/media/platform/nxp/dw100/
|
||||
F: include/uapi/linux/dw100.h
|
||||
|
||||
NXP i.MX 8QXP/8QM JPEG V4L2 DRIVER
|
||||
M: Mirela Rabulea <mirela.rabulea@nxp.com>
|
||||
R: NXP Linux Team <linux-imx@nxp.com>
|
||||
|
|
@ -17993,8 +18031,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
|
|||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: drivers/media/common/saa7146/
|
||||
F: drivers/media/pci/saa7146/
|
||||
F: drivers/staging/media/deprecated/saa7146/
|
||||
F: include/media/drv-intf/saa7146*
|
||||
|
||||
SAFESETID SECURITY MODULE
|
||||
|
|
@ -20417,6 +20454,7 @@ W: https://linuxtv.org
|
|||
Q: http://patchwork.linuxtv.org/project/linux-media/list/
|
||||
T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
|
||||
F: drivers/media/platform/ti/davinci/
|
||||
F: drivers/staging/media/deprecated/vpfe_capture/
|
||||
F: include/media/davinci/
|
||||
|
||||
TI ENHANCED QUADRATURE ENCODER PULSE (eQEP) DRIVER
|
||||
|
|
@ -20557,7 +20595,7 @@ S: Odd fixes
|
|||
W: https://linuxtv.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/admin-guide/media/tm6000*
|
||||
F: drivers/media/usb/tm6000/
|
||||
F: drivers/staging/media/deprecated/tm6000/
|
||||
|
||||
TMIO/SDHI MMC DRIVER
|
||||
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||
|
|
@ -20657,9 +20695,10 @@ F: include/linux/toshiba.h
|
|||
F: include/uapi/linux/toshiba.h
|
||||
|
||||
TOSHIBA TC358743 DRIVER
|
||||
M: Mats Randgaard <matrandg@cisco.com>
|
||||
M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/media/i2c/tc358743.txt
|
||||
F: drivers/media/i2c/tc358743*
|
||||
F: include/media/i2c/tc358743.h
|
||||
|
||||
|
|
@ -21315,7 +21354,7 @@ S: Maintained
|
|||
W: http://royale.zerezo.com/zr364xx/
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/admin-guide/media/zr364xx*
|
||||
F: drivers/media/usb/zr364xx/
|
||||
F: drivers/staging/media/deprecated/zr364xx/
|
||||
|
||||
USER-MODE LINUX (UML)
|
||||
M: Richard Weinberger <richard@nod.at>
|
||||
|
|
|
|||
|
|
@ -993,7 +993,7 @@
|
|||
touchscreen@41 {
|
||||
compatible = "st,stmpe811";
|
||||
reg = <0x41>;
|
||||
irq-gpio = <&gpio TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
|
||||
irq-gpio = <&gpio TEGRA_GPIO(V, 0) GPIO_ACTIVE_LOW>;
|
||||
interrupt-controller;
|
||||
id = <0>;
|
||||
blocks = <0x5>;
|
||||
|
|
|
|||
|
|
@ -976,7 +976,7 @@
|
|||
touchscreen@41 {
|
||||
compatible = "st,stmpe811";
|
||||
reg = <0x41>;
|
||||
irq-gpio = <&gpio TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
|
||||
irq-gpio = <&gpio TEGRA_GPIO(V, 0) GPIO_ACTIVE_LOW>;
|
||||
interrupt-controller;
|
||||
id = <0>;
|
||||
blocks = <0x5>;
|
||||
|
|
|
|||
|
|
@ -849,7 +849,7 @@
|
|||
touchscreen@41 {
|
||||
compatible = "st,stmpe811";
|
||||
reg = <0x41>;
|
||||
irq-gpio = <&gpio TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
|
||||
irq-gpio = <&gpio TEGRA_GPIO(V, 0) GPIO_ACTIVE_LOW>;
|
||||
interrupt-controller;
|
||||
id = <0>;
|
||||
blocks = <0x5>;
|
||||
|
|
|
|||
|
|
@ -141,13 +141,6 @@
|
|||
#define HTCPLD_GPIO_DOWN_DPAD HTCPLD_BASE(7, 4)
|
||||
#define HTCPLD_GPIO_ENTER_DPAD HTCPLD_BASE(7, 3)
|
||||
|
||||
/*
|
||||
* The htcpld chip requires a gpio write to a specific line
|
||||
* to re-enable interrupts after one has occurred.
|
||||
*/
|
||||
#define HTCPLD_GPIO_INT_RESET_HI HTCPLD_BASE(2, 7)
|
||||
#define HTCPLD_GPIO_INT_RESET_LO HTCPLD_BASE(2, 0)
|
||||
|
||||
/* Chip 5 */
|
||||
#define HTCPLD_IRQ_RIGHT_KBD HTCPLD_IRQ(0, 7)
|
||||
#define HTCPLD_IRQ_UP_KBD HTCPLD_IRQ(0, 6)
|
||||
|
|
@ -348,8 +341,6 @@ static struct htcpld_chip_platform_data htcpld_chips[] = {
|
|||
};
|
||||
|
||||
static struct htcpld_core_platform_data htcpld_pfdata = {
|
||||
.int_reset_gpio_hi = HTCPLD_GPIO_INT_RESET_HI,
|
||||
.int_reset_gpio_lo = HTCPLD_GPIO_INT_RESET_LO,
|
||||
.i2c_adapter_id = 1,
|
||||
|
||||
.chip = htcpld_chips,
|
||||
|
|
|
|||
|
|
@ -256,7 +256,6 @@ menuconfig ARCH_VEXPRESS
|
|||
select GPIOLIB
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_ARM_TWD if SMP
|
||||
select HAVE_PATA_PLATFORM
|
||||
select CLK_ICST
|
||||
select NO_IOPORT_MAP
|
||||
select PLAT_VERSATILE
|
||||
|
|
|
|||
|
|
@ -195,7 +195,6 @@ config ARM64
|
|||
select HAVE_IRQ_TIME_ACCOUNTING
|
||||
select HAVE_KVM
|
||||
select HAVE_NMI
|
||||
select HAVE_PATA_PLATFORM
|
||||
select HAVE_PERF_EVENTS
|
||||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
|
|
|
|||
|
|
@ -215,6 +215,11 @@ union scsw {
|
|||
#define SNS2_ENV_DATA_PRESENT 0x10
|
||||
#define SNS2_INPRECISE_END 0x04
|
||||
|
||||
/*
|
||||
* architectured values for PPRC errors
|
||||
*/
|
||||
#define SNS7_INVALID_ON_SEC 0x0e
|
||||
|
||||
/**
|
||||
* scsw_is_tm - check for transport mode scsw
|
||||
* @scsw: pointer to scsw
|
||||
|
|
|
|||
|
|
@ -182,6 +182,18 @@ typedef struct format_data_t {
|
|||
unsigned int intensity;
|
||||
} format_data_t;
|
||||
|
||||
/*
|
||||
* struct dasd_copypair_swap_data_t
|
||||
* represents all data necessary to issue a swap of the copy pair relation
|
||||
*/
|
||||
struct dasd_copypair_swap_data_t {
|
||||
char primary[20]; /* BUSID of primary */
|
||||
char secondary[20]; /* BUSID of secondary */
|
||||
|
||||
/* Reserved for future updates. */
|
||||
__u8 reserved[64];
|
||||
};
|
||||
|
||||
/*
|
||||
* values to be used for format_data_t.intensity
|
||||
* 0/8: normal format
|
||||
|
|
@ -326,6 +338,8 @@ struct dasd_snid_ioctl_data {
|
|||
#define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t)
|
||||
/* Release Allocated Space */
|
||||
#define BIODASDRAS _IOW(DASD_IOCTL_LETTER, 3, format_data_t)
|
||||
/* Swap copy pair relation */
|
||||
#define BIODASDCOPYPAIRSWAP _IOW(DASD_IOCTL_LETTER, 4, struct dasd_copypair_swap_data_t)
|
||||
|
||||
/* Get Sense Path Group ID (SNID) data */
|
||||
#define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data)
|
||||
|
|
|
|||
|
|
@ -254,17 +254,12 @@ void bfqg_stats_update_completion(struct bfq_group *bfqg, u64 start_time_ns,
|
|||
|
||||
#else /* CONFIG_BFQ_CGROUP_DEBUG */
|
||||
|
||||
void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
|
||||
blk_opf_t opf) { }
|
||||
void bfqg_stats_update_io_remove(struct bfq_group *bfqg, blk_opf_t opf) { }
|
||||
void bfqg_stats_update_io_merged(struct bfq_group *bfqg, blk_opf_t opf) { }
|
||||
void bfqg_stats_update_completion(struct bfq_group *bfqg, u64 start_time_ns,
|
||||
u64 io_start_time_ns, blk_opf_t opf) { }
|
||||
void bfqg_stats_update_dequeue(struct bfq_group *bfqg) { }
|
||||
void bfqg_stats_set_start_empty_time(struct bfq_group *bfqg) { }
|
||||
void bfqg_stats_update_idle_time(struct bfq_group *bfqg) { }
|
||||
void bfqg_stats_set_start_idle_time(struct bfq_group *bfqg) { }
|
||||
void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg) { }
|
||||
|
||||
#endif /* CONFIG_BFQ_CGROUP_DEBUG */
|
||||
|
||||
|
|
|
|||
|
|
@ -1925,7 +1925,7 @@ static void bfq_bfqq_handle_idle_busy_switch(struct bfq_data *bfqd,
|
|||
bfqq->service_from_backlogged = 0;
|
||||
bfq_clear_bfqq_softrt_update(bfqq);
|
||||
|
||||
bfq_add_bfqq_busy(bfqd, bfqq);
|
||||
bfq_add_bfqq_busy(bfqq);
|
||||
|
||||
/*
|
||||
* Expire in-service queue if preemption may be needed for
|
||||
|
|
@ -2419,7 +2419,7 @@ static void bfq_remove_request(struct request_queue *q,
|
|||
bfqq->next_rq = NULL;
|
||||
|
||||
if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) {
|
||||
bfq_del_bfqq_busy(bfqd, bfqq, false);
|
||||
bfq_del_bfqq_busy(bfqq, false);
|
||||
/*
|
||||
* bfqq emptied. In normal operation, when
|
||||
* bfqq is empty, bfqq->entity.service and
|
||||
|
|
@ -3098,7 +3098,7 @@ void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq)
|
|||
*/
|
||||
if (bfq_bfqq_busy(bfqq) && RB_EMPTY_ROOT(&bfqq->sort_list) &&
|
||||
bfqq != bfqd->in_service_queue)
|
||||
bfq_del_bfqq_busy(bfqd, bfqq, false);
|
||||
bfq_del_bfqq_busy(bfqq, false);
|
||||
|
||||
bfq_reassign_last_bfqq(bfqq, NULL);
|
||||
|
||||
|
|
@ -3908,7 +3908,7 @@ static bool __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
|||
*/
|
||||
bfqq->budget_timeout = jiffies;
|
||||
|
||||
bfq_del_bfqq_busy(bfqd, bfqq, true);
|
||||
bfq_del_bfqq_busy(bfqq, true);
|
||||
} else {
|
||||
bfq_requeue_bfqq(bfqd, bfqq, true);
|
||||
/*
|
||||
|
|
@ -5255,9 +5255,7 @@ void bfq_put_queue(struct bfq_queue *bfqq)
|
|||
struct hlist_node *n;
|
||||
struct bfq_group *bfqg = bfqq_group(bfqq);
|
||||
|
||||
if (bfqq->bfqd)
|
||||
bfq_log_bfqq(bfqq->bfqd, bfqq, "put_queue: %p %d",
|
||||
bfqq, bfqq->ref);
|
||||
bfq_log_bfqq(bfqq->bfqd, bfqq, "put_queue: %p %d", bfqq, bfqq->ref);
|
||||
|
||||
bfqq->ref--;
|
||||
if (bfqq->ref)
|
||||
|
|
@ -5321,7 +5319,7 @@ void bfq_put_queue(struct bfq_queue *bfqq)
|
|||
hlist_del_init(&item->woken_list_node);
|
||||
}
|
||||
|
||||
if (bfqq->bfqd && bfqq->bfqd->last_completed_rq_bfqq == bfqq)
|
||||
if (bfqq->bfqd->last_completed_rq_bfqq == bfqq)
|
||||
bfqq->bfqd->last_completed_rq_bfqq = NULL;
|
||||
|
||||
kmem_cache_free(bfq_pool, bfqq);
|
||||
|
|
|
|||
|
|
@ -993,20 +993,23 @@ void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
|
|||
/* ---------------- cgroups-support interface ---------------- */
|
||||
|
||||
void bfqg_stats_update_legacy_io(struct request_queue *q, struct request *rq);
|
||||
void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
|
||||
blk_opf_t opf);
|
||||
void bfqg_stats_update_io_remove(struct bfq_group *bfqg, blk_opf_t opf);
|
||||
void bfqg_stats_update_io_merged(struct bfq_group *bfqg, blk_opf_t opf);
|
||||
void bfqg_stats_update_completion(struct bfq_group *bfqg, u64 start_time_ns,
|
||||
u64 io_start_time_ns, blk_opf_t opf);
|
||||
void bfqg_stats_update_dequeue(struct bfq_group *bfqg);
|
||||
void bfqg_stats_set_start_empty_time(struct bfq_group *bfqg);
|
||||
void bfqg_stats_update_idle_time(struct bfq_group *bfqg);
|
||||
void bfqg_stats_set_start_idle_time(struct bfq_group *bfqg);
|
||||
void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg);
|
||||
void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
struct bfq_group *bfqg);
|
||||
|
||||
#ifdef CONFIG_BFQ_CGROUP_DEBUG
|
||||
void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
|
||||
blk_opf_t opf);
|
||||
void bfqg_stats_set_start_empty_time(struct bfq_group *bfqg);
|
||||
void bfqg_stats_update_idle_time(struct bfq_group *bfqg);
|
||||
void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg);
|
||||
#endif
|
||||
|
||||
void bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg);
|
||||
void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio);
|
||||
void bfq_end_wr_async(struct bfq_data *bfqd);
|
||||
|
|
@ -1077,9 +1080,8 @@ void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
|||
void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq);
|
||||
void bfq_requeue_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
bool expiration);
|
||||
void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
bool expiration);
|
||||
void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq);
|
||||
void bfq_del_bfqq_busy(struct bfq_queue *bfqq, bool expiration);
|
||||
void bfq_add_bfqq_busy(struct bfq_queue *bfqq);
|
||||
|
||||
/* --------------- end of interface of B-WF2Q+ ---------------- */
|
||||
|
||||
|
|
|
|||
|
|
@ -1651,9 +1651,10 @@ void bfq_requeue_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
|||
* the service tree. As a special case, it can be invoked during an
|
||||
* expiration.
|
||||
*/
|
||||
void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
bool expiration)
|
||||
void bfq_del_bfqq_busy(struct bfq_queue *bfqq, bool expiration)
|
||||
{
|
||||
struct bfq_data *bfqd = bfqq->bfqd;
|
||||
|
||||
bfq_log_bfqq(bfqd, bfqq, "del from busy");
|
||||
|
||||
bfq_clear_bfqq_busy(bfqq);
|
||||
|
|
@ -1674,8 +1675,10 @@ void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
|||
/*
|
||||
* Called when an inactive queue receives a new request.
|
||||
*/
|
||||
void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq)
|
||||
void bfq_add_bfqq_busy(struct bfq_queue *bfqq)
|
||||
{
|
||||
struct bfq_data *bfqd = bfqq->bfqd;
|
||||
|
||||
bfq_log_bfqq(bfqd, bfqq, "add to busy");
|
||||
|
||||
bfq_activate_bfqq(bfqd, bfqq);
|
||||
|
|
|
|||
13
block/bio.c
13
block/bio.c
|
|
@ -763,8 +763,6 @@ EXPORT_SYMBOL(bio_put);
|
|||
static int __bio_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp)
|
||||
{
|
||||
bio_set_flag(bio, BIO_CLONED);
|
||||
if (bio_flagged(bio_src, BIO_THROTTLED))
|
||||
bio_set_flag(bio, BIO_THROTTLED);
|
||||
bio->bi_ioprio = bio_src->bi_ioprio;
|
||||
bio->bi_iter = bio_src->bi_iter;
|
||||
|
||||
|
|
@ -1068,9 +1066,6 @@ void __bio_add_page(struct bio *bio, struct page *page,
|
|||
|
||||
bio->bi_iter.bi_size += len;
|
||||
bio->bi_vcnt++;
|
||||
|
||||
if (!bio_flagged(bio, BIO_WORKINGSET) && unlikely(PageWorkingset(page)))
|
||||
bio_set_flag(bio, BIO_WORKINGSET);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__bio_add_page);
|
||||
|
||||
|
|
@ -1279,9 +1274,6 @@ out:
|
|||
* fit into the bio, or are requested in @iter, whatever is smaller. If
|
||||
* MM encounters an error pinning the requested pages, it stops. Error
|
||||
* is returned only if 0 pages could be pinned.
|
||||
*
|
||||
* It's intended for direct IO, so doesn't do PSI tracking, the caller is
|
||||
* responsible for setting BIO_WORKINGSET if necessary.
|
||||
*/
|
||||
int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
|
||||
{
|
||||
|
|
@ -1297,8 +1289,6 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
|
|||
ret = __bio_iov_iter_get_pages(bio, iter);
|
||||
} while (!ret && iov_iter_count(iter) && !bio_full(bio, 0));
|
||||
|
||||
/* don't account direct I/O as memory stall */
|
||||
bio_clear_flag(bio, BIO_WORKINGSET);
|
||||
return bio->bi_vcnt ? 0 : ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bio_iov_iter_get_pages);
|
||||
|
|
@ -1757,7 +1747,8 @@ static int __init init_bio(void)
|
|||
cpuhp_setup_state_multi(CPUHP_BIO_DEAD, "block/bio:dead", NULL,
|
||||
bio_cpu_dead);
|
||||
|
||||
if (bioset_init(&fs_bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS))
|
||||
if (bioset_init(&fs_bio_set, BIO_POOL_SIZE, 0,
|
||||
BIOSET_NEED_BVECS | BIOSET_PERCPU_CACHE))
|
||||
panic("bio: can't allocate bios\n");
|
||||
|
||||
if (bioset_integrity_create(&fs_bio_set, BIO_POOL_SIZE))
|
||||
|
|
|
|||
|
|
@ -202,19 +202,19 @@ static inline struct blkcg *blkcg_parent(struct blkcg *blkcg)
|
|||
/**
|
||||
* blkg_alloc - allocate a blkg
|
||||
* @blkcg: block cgroup the new blkg is associated with
|
||||
* @q: request_queue the new blkg is associated with
|
||||
* @disk: gendisk the new blkg is associated with
|
||||
* @gfp_mask: allocation mask to use
|
||||
*
|
||||
* Allocate a new blkg assocating @blkcg and @q.
|
||||
*/
|
||||
static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,
|
||||
static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
struct blkcg_gq *blkg;
|
||||
int i, cpu;
|
||||
|
||||
/* alloc and init base part */
|
||||
blkg = kzalloc_node(sizeof(*blkg), gfp_mask, q->node);
|
||||
blkg = kzalloc_node(sizeof(*blkg), gfp_mask, disk->queue->node);
|
||||
if (!blkg)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -225,10 +225,10 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,
|
|||
if (!blkg->iostat_cpu)
|
||||
goto err_free;
|
||||
|
||||
if (!blk_get_queue(q))
|
||||
if (!blk_get_queue(disk->queue))
|
||||
goto err_free;
|
||||
|
||||
blkg->q = q;
|
||||
blkg->q = disk->queue;
|
||||
INIT_LIST_HEAD(&blkg->q_node);
|
||||
spin_lock_init(&blkg->async_bio_lock);
|
||||
bio_list_init(&blkg->async_bios);
|
||||
|
|
@ -243,11 +243,11 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,
|
|||
struct blkcg_policy *pol = blkcg_policy[i];
|
||||
struct blkg_policy_data *pd;
|
||||
|
||||
if (!blkcg_policy_enabled(q, pol))
|
||||
if (!blkcg_policy_enabled(disk->queue, pol))
|
||||
continue;
|
||||
|
||||
/* alloc per-policy data and attach it to blkg */
|
||||
pd = pol->pd_alloc_fn(gfp_mask, q, blkcg);
|
||||
pd = pol->pd_alloc_fn(gfp_mask, disk->queue, blkcg);
|
||||
if (!pd)
|
||||
goto err_free;
|
||||
|
||||
|
|
@ -263,45 +263,20 @@ err_free:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg,
|
||||
struct request_queue *q, bool update_hint)
|
||||
{
|
||||
struct blkcg_gq *blkg;
|
||||
|
||||
/*
|
||||
* Hint didn't match. Look up from the radix tree. Note that the
|
||||
* hint can only be updated under queue_lock as otherwise @blkg
|
||||
* could have already been removed from blkg_tree. The caller is
|
||||
* responsible for grabbing queue_lock if @update_hint.
|
||||
*/
|
||||
blkg = radix_tree_lookup(&blkcg->blkg_tree, q->id);
|
||||
if (blkg && blkg->q == q) {
|
||||
if (update_hint) {
|
||||
lockdep_assert_held(&q->queue_lock);
|
||||
rcu_assign_pointer(blkcg->blkg_hint, blkg);
|
||||
}
|
||||
return blkg;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blkg_lookup_slowpath);
|
||||
|
||||
/*
|
||||
* If @new_blkg is %NULL, this function tries to allocate a new one as
|
||||
* necessary using %GFP_NOWAIT. @new_blkg is always consumed on return.
|
||||
*/
|
||||
static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
|
||||
struct request_queue *q,
|
||||
static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
|
||||
struct blkcg_gq *new_blkg)
|
||||
{
|
||||
struct blkcg_gq *blkg;
|
||||
int i, ret;
|
||||
|
||||
lockdep_assert_held(&q->queue_lock);
|
||||
lockdep_assert_held(&disk->queue->queue_lock);
|
||||
|
||||
/* request_queue is dying, do not create/recreate a blkg */
|
||||
if (blk_queue_dying(q)) {
|
||||
if (blk_queue_dying(disk->queue)) {
|
||||
ret = -ENODEV;
|
||||
goto err_free_blkg;
|
||||
}
|
||||
|
|
@ -314,7 +289,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
|
|||
|
||||
/* allocate */
|
||||
if (!new_blkg) {
|
||||
new_blkg = blkg_alloc(blkcg, q, GFP_NOWAIT | __GFP_NOWARN);
|
||||
new_blkg = blkg_alloc(blkcg, disk, GFP_NOWAIT | __GFP_NOWARN);
|
||||
if (unlikely(!new_blkg)) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put_css;
|
||||
|
|
@ -324,7 +299,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
|
|||
|
||||
/* link parent */
|
||||
if (blkcg_parent(blkcg)) {
|
||||
blkg->parent = __blkg_lookup(blkcg_parent(blkcg), q, false);
|
||||
blkg->parent = blkg_lookup(blkcg_parent(blkcg), disk->queue);
|
||||
if (WARN_ON_ONCE(!blkg->parent)) {
|
||||
ret = -ENODEV;
|
||||
goto err_put_css;
|
||||
|
|
@ -342,10 +317,10 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
|
|||
|
||||
/* insert */
|
||||
spin_lock(&blkcg->lock);
|
||||
ret = radix_tree_insert(&blkcg->blkg_tree, q->id, blkg);
|
||||
ret = radix_tree_insert(&blkcg->blkg_tree, disk->queue->id, blkg);
|
||||
if (likely(!ret)) {
|
||||
hlist_add_head_rcu(&blkg->blkcg_node, &blkcg->blkg_list);
|
||||
list_add(&blkg->q_node, &q->blkg_list);
|
||||
list_add(&blkg->q_node, &disk->queue->blkg_list);
|
||||
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++) {
|
||||
struct blkcg_policy *pol = blkcg_policy[i];
|
||||
|
|
@ -374,19 +349,20 @@ err_free_blkg:
|
|||
/**
|
||||
* blkg_lookup_create - lookup blkg, try to create one if not there
|
||||
* @blkcg: blkcg of interest
|
||||
* @q: request_queue of interest
|
||||
* @disk: gendisk of interest
|
||||
*
|
||||
* Lookup blkg for the @blkcg - @q pair. If it doesn't exist, try to
|
||||
* Lookup blkg for the @blkcg - @disk pair. If it doesn't exist, try to
|
||||
* create one. blkg creation is performed recursively from blkcg_root such
|
||||
* that all non-root blkg's have access to the parent blkg. This function
|
||||
* should be called under RCU read lock and takes @q->queue_lock.
|
||||
* should be called under RCU read lock and takes @disk->queue->queue_lock.
|
||||
*
|
||||
* Returns the blkg or the closest blkg if blkg_create() fails as it walks
|
||||
* down from root.
|
||||
*/
|
||||
static struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
|
||||
struct request_queue *q)
|
||||
struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct blkcg_gq *blkg;
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -397,9 +373,13 @@ static struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
|
|||
return blkg;
|
||||
|
||||
spin_lock_irqsave(&q->queue_lock, flags);
|
||||
blkg = __blkg_lookup(blkcg, q, true);
|
||||
if (blkg)
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create blkgs walking down from blkcg_root to @blkcg, so that all
|
||||
|
|
@ -412,7 +392,7 @@ static struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
|
|||
struct blkcg_gq *ret_blkg = q->root_blkg;
|
||||
|
||||
while (parent) {
|
||||
blkg = __blkg_lookup(parent, q, false);
|
||||
blkg = blkg_lookup(parent, q);
|
||||
if (blkg) {
|
||||
/* remember closest blkg */
|
||||
ret_blkg = blkg;
|
||||
|
|
@ -422,7 +402,7 @@ static struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
|
|||
parent = blkcg_parent(parent);
|
||||
}
|
||||
|
||||
blkg = blkg_create(pos, q, NULL);
|
||||
blkg = blkg_create(pos, disk, NULL);
|
||||
if (IS_ERR(blkg)) {
|
||||
blkg = ret_blkg;
|
||||
break;
|
||||
|
|
@ -476,14 +456,9 @@ static void blkg_destroy(struct blkcg_gq *blkg)
|
|||
percpu_ref_kill(&blkg->refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_destroy_all - destroy all blkgs associated with a request_queue
|
||||
* @q: request_queue of interest
|
||||
*
|
||||
* Destroy all blkgs associated with @q.
|
||||
*/
|
||||
static void blkg_destroy_all(struct request_queue *q)
|
||||
static void blkg_destroy_all(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct blkcg_gq *blkg, *n;
|
||||
int count = BLKG_DESTROY_BATCH_SIZE;
|
||||
|
||||
|
|
@ -616,19 +591,6 @@ u64 __blkg_prfill_u64(struct seq_file *sf, struct blkg_policy_data *pd, u64 v)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(__blkg_prfill_u64);
|
||||
|
||||
/* Performs queue bypass and policy enabled checks then looks up blkg. */
|
||||
static struct blkcg_gq *blkg_lookup_check(struct blkcg *blkcg,
|
||||
const struct blkcg_policy *pol,
|
||||
struct request_queue *q)
|
||||
{
|
||||
WARN_ON_ONCE(!rcu_read_lock_held());
|
||||
lockdep_assert_held(&q->queue_lock);
|
||||
|
||||
if (!blkcg_policy_enabled(q, pol))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
return __blkg_lookup(blkcg, q, true /* update_hint */);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_conf_open_bdev - parse and open bdev for per-blkg config update
|
||||
* @inputp: input string pointer
|
||||
|
|
@ -684,6 +646,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
|||
__acquires(rcu) __acquires(&bdev->bd_queue->queue_lock)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
struct gendisk *disk;
|
||||
struct request_queue *q;
|
||||
struct blkcg_gq *blkg;
|
||||
int ret;
|
||||
|
|
@ -691,8 +654,8 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
|||
bdev = blkcg_conf_open_bdev(&input);
|
||||
if (IS_ERR(bdev))
|
||||
return PTR_ERR(bdev);
|
||||
|
||||
q = bdev_get_queue(bdev);
|
||||
disk = bdev->bd_disk;
|
||||
q = disk->queue;
|
||||
|
||||
/*
|
||||
* blkcg_deactivate_policy() requires queue to be frozen, we can grab
|
||||
|
|
@ -705,12 +668,12 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
|||
rcu_read_lock();
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
|
||||
blkg = blkg_lookup_check(blkcg, pol, q);
|
||||
if (IS_ERR(blkg)) {
|
||||
ret = PTR_ERR(blkg);
|
||||
if (!blkcg_policy_enabled(q, pol)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
blkg = blkg_lookup(blkcg, q);
|
||||
if (blkg)
|
||||
goto success;
|
||||
|
||||
|
|
@ -724,7 +687,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
|||
struct blkcg_gq *new_blkg;
|
||||
|
||||
parent = blkcg_parent(blkcg);
|
||||
while (parent && !__blkg_lookup(parent, q, false)) {
|
||||
while (parent && !blkg_lookup(parent, q)) {
|
||||
pos = parent;
|
||||
parent = blkcg_parent(parent);
|
||||
}
|
||||
|
|
@ -733,7 +696,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
|||
spin_unlock_irq(&q->queue_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
new_blkg = blkg_alloc(pos, q, GFP_KERNEL);
|
||||
new_blkg = blkg_alloc(pos, disk, GFP_KERNEL);
|
||||
if (unlikely(!new_blkg)) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_exit_queue;
|
||||
|
|
@ -748,17 +711,17 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
|||
rcu_read_lock();
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
|
||||
blkg = blkg_lookup_check(pos, pol, q);
|
||||
if (IS_ERR(blkg)) {
|
||||
ret = PTR_ERR(blkg);
|
||||
if (!blkcg_policy_enabled(q, pol)) {
|
||||
blkg_free(new_blkg);
|
||||
ret = -EOPNOTSUPP;
|
||||
goto fail_preloaded;
|
||||
}
|
||||
|
||||
blkg = blkg_lookup(pos, q);
|
||||
if (blkg) {
|
||||
blkg_free(new_blkg);
|
||||
} else {
|
||||
blkg = blkg_create(pos, q, new_blkg);
|
||||
blkg = blkg_create(pos, disk, new_blkg);
|
||||
if (IS_ERR(blkg)) {
|
||||
ret = PTR_ERR(blkg);
|
||||
goto fail_preloaded;
|
||||
|
|
@ -915,8 +878,7 @@ static void blkcg_fill_root_iostats(void)
|
|||
class_dev_iter_init(&iter, &block_class, NULL, &disk_type);
|
||||
while ((dev = class_dev_iter_next(&iter))) {
|
||||
struct block_device *bdev = dev_to_bdev(dev);
|
||||
struct blkcg_gq *blkg =
|
||||
blk_queue_root_blkg(bdev_get_queue(bdev));
|
||||
struct blkcg_gq *blkg = bdev->bd_disk->queue->root_blkg;
|
||||
struct blkg_iostat tmp;
|
||||
int cpu;
|
||||
unsigned long flags;
|
||||
|
|
@ -1255,25 +1217,16 @@ static int blkcg_css_online(struct cgroup_subsys_state *css)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_init_queue - initialize blkcg part of request queue
|
||||
* @q: request_queue to initialize
|
||||
*
|
||||
* Called from blk_alloc_queue(). Responsible for initializing blkcg
|
||||
* part of new request_queue @q.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno on failure.
|
||||
*/
|
||||
int blkcg_init_queue(struct request_queue *q)
|
||||
int blkcg_init_disk(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct blkcg_gq *new_blkg, *blkg;
|
||||
bool preloaded;
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&q->blkg_list);
|
||||
|
||||
new_blkg = blkg_alloc(&blkcg_root, q, GFP_KERNEL);
|
||||
new_blkg = blkg_alloc(&blkcg_root, disk, GFP_KERNEL);
|
||||
if (!new_blkg)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -1282,7 +1235,7 @@ int blkcg_init_queue(struct request_queue *q)
|
|||
/* Make sure the root blkg exists. */
|
||||
/* spin_lock_irq can serve as RCU read-side critical section. */
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
blkg = blkg_create(&blkcg_root, q, new_blkg);
|
||||
blkg = blkg_create(&blkcg_root, disk, new_blkg);
|
||||
if (IS_ERR(blkg))
|
||||
goto err_unlock;
|
||||
q->root_blkg = blkg;
|
||||
|
|
@ -1291,25 +1244,26 @@ int blkcg_init_queue(struct request_queue *q)
|
|||
if (preloaded)
|
||||
radix_tree_preload_end();
|
||||
|
||||
ret = blk_ioprio_init(q);
|
||||
ret = blk_ioprio_init(disk);
|
||||
if (ret)
|
||||
goto err_destroy_all;
|
||||
|
||||
ret = blk_throtl_init(q);
|
||||
ret = blk_throtl_init(disk);
|
||||
if (ret)
|
||||
goto err_destroy_all;
|
||||
goto err_ioprio_exit;
|
||||
|
||||
ret = blk_iolatency_init(q);
|
||||
if (ret) {
|
||||
blk_throtl_exit(q);
|
||||
blk_ioprio_exit(q);
|
||||
goto err_destroy_all;
|
||||
}
|
||||
ret = blk_iolatency_init(disk);
|
||||
if (ret)
|
||||
goto err_throtl_exit;
|
||||
|
||||
return 0;
|
||||
|
||||
err_throtl_exit:
|
||||
blk_throtl_exit(disk);
|
||||
err_ioprio_exit:
|
||||
blk_ioprio_exit(disk);
|
||||
err_destroy_all:
|
||||
blkg_destroy_all(q);
|
||||
blkg_destroy_all(disk);
|
||||
return ret;
|
||||
err_unlock:
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
|
|
@ -1318,16 +1272,10 @@ err_unlock:
|
|||
return PTR_ERR(blkg);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_exit_queue - exit and release blkcg part of request_queue
|
||||
* @q: request_queue being released
|
||||
*
|
||||
* Called from blk_exit_queue(). Responsible for exiting blkcg part.
|
||||
*/
|
||||
void blkcg_exit_queue(struct request_queue *q)
|
||||
void blkcg_exit_disk(struct gendisk *disk)
|
||||
{
|
||||
blkg_destroy_all(q);
|
||||
blk_throtl_exit(q);
|
||||
blkg_destroy_all(disk);
|
||||
blk_throtl_exit(disk);
|
||||
}
|
||||
|
||||
static void blkcg_bind(struct cgroup_subsys_state *root_css)
|
||||
|
|
@ -1836,13 +1784,13 @@ out:
|
|||
|
||||
/**
|
||||
* blkcg_schedule_throttle - this task needs to check for throttling
|
||||
* @q: the request queue IO was submitted on
|
||||
* @gendisk: disk to throttle
|
||||
* @use_memdelay: do we charge this to memory delay for PSI
|
||||
*
|
||||
* This is called by the IO controller when we know there's delay accumulated
|
||||
* for the blkg for this task. We do not pass the blkg because there are places
|
||||
* we call this that may not have that information, the swapping code for
|
||||
* instance will only have a request_queue at that point. This set's the
|
||||
* instance will only have a block_device at that point. This set's the
|
||||
* notify_resume for the task to check and see if it requires throttling before
|
||||
* returning to user space.
|
||||
*
|
||||
|
|
@ -1851,8 +1799,10 @@ out:
|
|||
* throttle once. If the task needs to be throttled again it'll need to be
|
||||
* re-set at the next time we see the task.
|
||||
*/
|
||||
void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay)
|
||||
void blkcg_schedule_throttle(struct gendisk *disk, bool use_memdelay)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
|
||||
if (unlikely(current->flags & PF_KTHREAD))
|
||||
return;
|
||||
|
||||
|
|
@ -1902,8 +1852,7 @@ static inline struct blkcg_gq *blkg_tryget_closest(struct bio *bio,
|
|||
struct blkcg_gq *blkg, *ret_blkg = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
blkg = blkg_lookup_create(css_to_blkcg(css),
|
||||
bdev_get_queue(bio->bi_bdev));
|
||||
blkg = blkg_lookup_create(css_to_blkcg(css), bio->bi_bdev->bd_disk);
|
||||
while (blkg) {
|
||||
if (blkg_tryget(blkg)) {
|
||||
ret_blkg = blkg;
|
||||
|
|
|
|||
|
|
@ -178,10 +178,8 @@ struct blkcg_policy {
|
|||
extern struct blkcg blkcg_root;
|
||||
extern bool blkcg_debug_stats;
|
||||
|
||||
struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg,
|
||||
struct request_queue *q, bool update_hint);
|
||||
int blkcg_init_queue(struct request_queue *q);
|
||||
void blkcg_exit_queue(struct request_queue *q);
|
||||
int blkcg_init_disk(struct gendisk *disk);
|
||||
void blkcg_exit_disk(struct gendisk *disk);
|
||||
|
||||
/* Blkio controller policy registration */
|
||||
int blkcg_policy_register(struct blkcg_policy *pol);
|
||||
|
|
@ -227,22 +225,21 @@ static inline bool bio_issue_as_root_blkg(struct bio *bio)
|
|||
}
|
||||
|
||||
/**
|
||||
* __blkg_lookup - internal version of blkg_lookup()
|
||||
* blkg_lookup - lookup blkg for the specified blkcg - q pair
|
||||
* @blkcg: blkcg of interest
|
||||
* @q: request_queue of interest
|
||||
* @update_hint: whether to update lookup hint with the result or not
|
||||
*
|
||||
* This is internal version and shouldn't be used by policy
|
||||
* implementations. Looks up blkgs for the @blkcg - @q pair regardless of
|
||||
* @q's bypass state. If @update_hint is %true, the caller should be
|
||||
* holding @q->queue_lock and lookup hint is updated on success.
|
||||
* Lookup blkg for the @blkcg - @q pair.
|
||||
|
||||
* Must be called in a RCU critical section.
|
||||
*/
|
||||
static inline struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg,
|
||||
struct request_queue *q,
|
||||
bool update_hint)
|
||||
static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg,
|
||||
struct request_queue *q)
|
||||
{
|
||||
struct blkcg_gq *blkg;
|
||||
|
||||
WARN_ON_ONCE(!rcu_read_lock_held());
|
||||
|
||||
if (blkcg == &blkcg_root)
|
||||
return q->root_blkg;
|
||||
|
||||
|
|
@ -250,33 +247,10 @@ static inline struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg,
|
|||
if (blkg && blkg->q == q)
|
||||
return blkg;
|
||||
|
||||
return blkg_lookup_slowpath(blkcg, q, update_hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_lookup - lookup blkg for the specified blkcg - q pair
|
||||
* @blkcg: blkcg of interest
|
||||
* @q: request_queue of interest
|
||||
*
|
||||
* Lookup blkg for the @blkcg - @q pair. This function should be called
|
||||
* under RCU read lock.
|
||||
*/
|
||||
static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg,
|
||||
struct request_queue *q)
|
||||
{
|
||||
WARN_ON_ONCE(!rcu_read_lock_held());
|
||||
return __blkg_lookup(blkcg, q, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_queue_root_blkg - return blkg for the (blkcg_root, @q) pair
|
||||
* @q: request_queue of interest
|
||||
*
|
||||
* Lookup blkg for @q at the root level. See also blkg_lookup().
|
||||
*/
|
||||
static inline struct blkcg_gq *blk_queue_root_blkg(struct request_queue *q)
|
||||
{
|
||||
return q->root_blkg;
|
||||
blkg = radix_tree_lookup(&blkcg->blkg_tree, q->id);
|
||||
if (blkg && blkg->q != q)
|
||||
blkg = NULL;
|
||||
return blkg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -373,8 +347,8 @@ static inline void blkg_put(struct blkcg_gq *blkg)
|
|||
*/
|
||||
#define blkg_for_each_descendant_pre(d_blkg, pos_css, p_blkg) \
|
||||
css_for_each_descendant_pre((pos_css), &(p_blkg)->blkcg->css) \
|
||||
if (((d_blkg) = __blkg_lookup(css_to_blkcg(pos_css), \
|
||||
(p_blkg)->q, false)))
|
||||
if (((d_blkg) = blkg_lookup(css_to_blkcg(pos_css), \
|
||||
(p_blkg)->q)))
|
||||
|
||||
/**
|
||||
* blkg_for_each_descendant_post - post-order walk of a blkg's descendants
|
||||
|
|
@ -388,8 +362,8 @@ static inline void blkg_put(struct blkcg_gq *blkg)
|
|||
*/
|
||||
#define blkg_for_each_descendant_post(d_blkg, pos_css, p_blkg) \
|
||||
css_for_each_descendant_post((pos_css), &(p_blkg)->blkcg->css) \
|
||||
if (((d_blkg) = __blkg_lookup(css_to_blkcg(pos_css), \
|
||||
(p_blkg)->q, false)))
|
||||
if (((d_blkg) = blkg_lookup(css_to_blkcg(pos_css), \
|
||||
(p_blkg)->q)))
|
||||
|
||||
bool __blkcg_punt_bio_submit(struct bio *bio);
|
||||
|
||||
|
|
@ -507,10 +481,8 @@ struct blkcg {
|
|||
};
|
||||
|
||||
static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { return NULL; }
|
||||
static inline struct blkcg_gq *blk_queue_root_blkg(struct request_queue *q)
|
||||
{ return NULL; }
|
||||
static inline int blkcg_init_queue(struct request_queue *q) { return 0; }
|
||||
static inline void blkcg_exit_queue(struct request_queue *q) { }
|
||||
static inline int blkcg_init_disk(struct gendisk *disk) { return 0; }
|
||||
static inline void blkcg_exit_disk(struct gendisk *disk) { }
|
||||
static inline int blkcg_policy_register(struct blkcg_policy *pol) { return 0; }
|
||||
static inline void blkcg_policy_unregister(struct blkcg_policy *pol) { }
|
||||
static inline int blkcg_activate_policy(struct request_queue *q,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include <linux/t10-pi.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/psi.h>
|
||||
#include <linux/part_stat.h>
|
||||
#include <linux/sched/sysctl.h>
|
||||
#include <linux/blk-crypto.h>
|
||||
|
|
@ -487,18 +486,15 @@ static int __init fail_make_request_debugfs(void)
|
|||
late_initcall(fail_make_request_debugfs);
|
||||
#endif /* CONFIG_FAIL_MAKE_REQUEST */
|
||||
|
||||
static inline bool bio_check_ro(struct bio *bio)
|
||||
static inline void bio_check_ro(struct bio *bio)
|
||||
{
|
||||
if (op_is_write(bio_op(bio)) && bdev_read_only(bio->bi_bdev)) {
|
||||
if (op_is_flush(bio->bi_opf) && !bio_sectors(bio))
|
||||
return false;
|
||||
return;
|
||||
pr_warn("Trying to write to read-only block-device %pg\n",
|
||||
bio->bi_bdev);
|
||||
/* Older lvm-tools actually trigger this */
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static noinline int should_fail_bio(struct bio *bio)
|
||||
|
|
@ -717,13 +713,12 @@ void submit_bio_noacct(struct bio *bio)
|
|||
* For a REQ_NOWAIT based request, return -EOPNOTSUPP
|
||||
* if queue does not support NOWAIT.
|
||||
*/
|
||||
if ((bio->bi_opf & REQ_NOWAIT) && !blk_queue_nowait(q))
|
||||
if ((bio->bi_opf & REQ_NOWAIT) && !bdev_nowait(bdev))
|
||||
goto not_supported;
|
||||
|
||||
if (should_fail_bio(bio))
|
||||
goto end_io;
|
||||
if (unlikely(bio_check_ro(bio)))
|
||||
goto end_io;
|
||||
bio_check_ro(bio);
|
||||
if (!bio_flagged(bio, BIO_REMAPPED)) {
|
||||
if (unlikely(bio_check_eod(bio)))
|
||||
goto end_io;
|
||||
|
|
@ -814,7 +809,7 @@ EXPORT_SYMBOL(submit_bio_noacct);
|
|||
*
|
||||
* The success/failure status of the request, along with notification of
|
||||
* completion, is delivered asynchronously through the ->bi_end_io() callback
|
||||
* in @bio. The bio must NOT be touched by thecaller until ->bi_end_io() has
|
||||
* in @bio. The bio must NOT be touched by the caller until ->bi_end_io() has
|
||||
* been called.
|
||||
*/
|
||||
void submit_bio(struct bio *bio)
|
||||
|
|
@ -829,22 +824,6 @@ void submit_bio(struct bio *bio)
|
|||
count_vm_events(PGPGOUT, bio_sectors(bio));
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're reading data that is part of the userspace workingset, count
|
||||
* submission time as memory stall. When the device is congested, or
|
||||
* the submitting cgroup IO-throttled, submission can be a significant
|
||||
* part of overall IO time.
|
||||
*/
|
||||
if (unlikely(bio_op(bio) == REQ_OP_READ &&
|
||||
bio_flagged(bio, BIO_WORKINGSET))) {
|
||||
unsigned long pflags;
|
||||
|
||||
psi_memstall_enter(&pflags);
|
||||
submit_bio_noacct(bio);
|
||||
psi_memstall_leave(&pflags);
|
||||
return;
|
||||
}
|
||||
|
||||
submit_bio_noacct(bio);
|
||||
}
|
||||
EXPORT_SYMBOL(submit_bio);
|
||||
|
|
@ -871,6 +850,12 @@ int bio_poll(struct bio *bio, struct io_comp_batch *iob, unsigned int flags)
|
|||
!test_bit(QUEUE_FLAG_POLL, &q->queue_flags))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* As the requests that require a zone lock are not plugged in the
|
||||
* first place, directly accessing the plug instead of using
|
||||
* blk_mq_plug() should not have any consequences during flushing for
|
||||
* zoned devices.
|
||||
*/
|
||||
blk_flush_plug(current->plug, false);
|
||||
|
||||
if (bio_queue_enter(bio))
|
||||
|
|
|
|||
|
|
@ -205,7 +205,6 @@ static void blk_flush_complete_seq(struct request *rq,
|
|||
* flush data request completion path. Restore @rq for
|
||||
* normal completion and end it.
|
||||
*/
|
||||
BUG_ON(!list_empty(&rq->queuelist));
|
||||
list_del_init(&rq->flush.list);
|
||||
blk_flush_restore_request(rq);
|
||||
blk_mq_end_request(rq, error);
|
||||
|
|
@ -218,7 +217,8 @@ static void blk_flush_complete_seq(struct request *rq,
|
|||
blk_kick_flush(q, fq, cmd_flags);
|
||||
}
|
||||
|
||||
static void flush_end_io(struct request *flush_rq, blk_status_t error)
|
||||
static enum rq_end_io_ret flush_end_io(struct request *flush_rq,
|
||||
blk_status_t error)
|
||||
{
|
||||
struct request_queue *q = flush_rq->q;
|
||||
struct list_head *running;
|
||||
|
|
@ -232,7 +232,7 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
|
|||
if (!req_ref_put_and_test(flush_rq)) {
|
||||
fq->rq_status = error;
|
||||
spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
|
||||
return;
|
||||
return RQ_END_IO_NONE;
|
||||
}
|
||||
|
||||
blk_account_io_flush(flush_rq);
|
||||
|
|
@ -269,6 +269,7 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
|
|||
}
|
||||
|
||||
spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
|
||||
return RQ_END_IO_NONE;
|
||||
}
|
||||
|
||||
bool is_flush_rq(struct request *rq)
|
||||
|
|
@ -354,7 +355,8 @@ static void blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq,
|
|||
blk_flush_queue_rq(flush_rq, false);
|
||||
}
|
||||
|
||||
static void mq_flush_data_end_io(struct request *rq, blk_status_t error)
|
||||
static enum rq_end_io_ret mq_flush_data_end_io(struct request *rq,
|
||||
blk_status_t error)
|
||||
{
|
||||
struct request_queue *q = rq->q;
|
||||
struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
|
||||
|
|
@ -376,6 +378,7 @@ static void mq_flush_data_end_io(struct request *rq, blk_status_t error)
|
|||
spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
|
||||
|
||||
blk_mq_sched_restart(hctx);
|
||||
return RQ_END_IO_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -664,17 +664,13 @@ static struct ioc *q_to_ioc(struct request_queue *q)
|
|||
return rqos_to_ioc(rq_qos_id(q, RQ_QOS_COST));
|
||||
}
|
||||
|
||||
static const char *q_name(struct request_queue *q)
|
||||
{
|
||||
if (blk_queue_registered(q))
|
||||
return kobject_name(q->kobj.parent);
|
||||
else
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
static const char __maybe_unused *ioc_name(struct ioc *ioc)
|
||||
{
|
||||
return q_name(ioc->rqos.q);
|
||||
struct gendisk *disk = ioc->rqos.q->disk;
|
||||
|
||||
if (!disk)
|
||||
return "<unknown>";
|
||||
return disk->disk_name;
|
||||
}
|
||||
|
||||
static struct ioc_gq *pd_to_iocg(struct blkg_policy_data *pd)
|
||||
|
|
@ -1430,7 +1426,7 @@ static int iocg_wake_fn(struct wait_queue_entry *wq_entry, unsigned mode,
|
|||
int flags, void *key)
|
||||
{
|
||||
struct iocg_wait *wait = container_of(wq_entry, struct iocg_wait, wait);
|
||||
struct iocg_wake_ctx *ctx = (struct iocg_wake_ctx *)key;
|
||||
struct iocg_wake_ctx *ctx = key;
|
||||
u64 cost = abs_cost_to_cost(wait->abs_cost, ctx->hw_inuse);
|
||||
|
||||
ctx->vbudget -= cost;
|
||||
|
|
@ -2640,7 +2636,7 @@ retry_lock:
|
|||
if (use_debt) {
|
||||
iocg_incur_debt(iocg, abs_cost, &now);
|
||||
if (iocg_kick_delay(iocg, &now))
|
||||
blkcg_schedule_throttle(rqos->q,
|
||||
blkcg_schedule_throttle(rqos->q->disk,
|
||||
(bio->bi_opf & REQ_SWAP) == REQ_SWAP);
|
||||
iocg_unlock(iocg, ioc_locked, &flags);
|
||||
return;
|
||||
|
|
@ -2741,7 +2737,7 @@ static void ioc_rqos_merge(struct rq_qos *rqos, struct request *rq,
|
|||
if (likely(!list_empty(&iocg->active_list))) {
|
||||
iocg_incur_debt(iocg, abs_cost, &now);
|
||||
if (iocg_kick_delay(iocg, &now))
|
||||
blkcg_schedule_throttle(rqos->q,
|
||||
blkcg_schedule_throttle(rqos->q->disk,
|
||||
(bio->bi_opf & REQ_SWAP) == REQ_SWAP);
|
||||
} else {
|
||||
iocg_commit_bio(iocg, bio, abs_cost, cost);
|
||||
|
|
@ -2832,8 +2828,9 @@ static struct rq_qos_ops ioc_rqos_ops = {
|
|||
.exit = ioc_rqos_exit,
|
||||
};
|
||||
|
||||
static int blk_iocost_init(struct request_queue *q)
|
||||
static int blk_iocost_init(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct ioc *ioc;
|
||||
struct rq_qos *rqos;
|
||||
int i, cpu, ret;
|
||||
|
|
@ -3170,6 +3167,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
|
|||
size_t nbytes, loff_t off)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
struct gendisk *disk;
|
||||
struct ioc *ioc;
|
||||
u32 qos[NR_QOS_PARAMS];
|
||||
bool enable, user;
|
||||
|
|
@ -3180,12 +3178,13 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
|
|||
if (IS_ERR(bdev))
|
||||
return PTR_ERR(bdev);
|
||||
|
||||
ioc = q_to_ioc(bdev_get_queue(bdev));
|
||||
disk = bdev->bd_disk;
|
||||
ioc = q_to_ioc(disk->queue);
|
||||
if (!ioc) {
|
||||
ret = blk_iocost_init(bdev_get_queue(bdev));
|
||||
ret = blk_iocost_init(disk);
|
||||
if (ret)
|
||||
goto err;
|
||||
ioc = q_to_ioc(bdev_get_queue(bdev));
|
||||
ioc = q_to_ioc(disk->queue);
|
||||
}
|
||||
|
||||
spin_lock_irq(&ioc->lock);
|
||||
|
|
@ -3262,11 +3261,11 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
|
|||
spin_lock_irq(&ioc->lock);
|
||||
|
||||
if (enable) {
|
||||
blk_stat_enable_accounting(ioc->rqos.q);
|
||||
blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, ioc->rqos.q);
|
||||
blk_stat_enable_accounting(disk->queue);
|
||||
blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue);
|
||||
ioc->enabled = true;
|
||||
} else {
|
||||
blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, ioc->rqos.q);
|
||||
blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue);
|
||||
ioc->enabled = false;
|
||||
}
|
||||
|
||||
|
|
@ -3349,7 +3348,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
|
|||
|
||||
ioc = q_to_ioc(bdev_get_queue(bdev));
|
||||
if (!ioc) {
|
||||
ret = blk_iocost_init(bdev_get_queue(bdev));
|
||||
ret = blk_iocost_init(bdev->bd_disk);
|
||||
if (ret)
|
||||
goto err;
|
||||
ioc = q_to_ioc(bdev_get_queue(bdev));
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ static void __blkcg_iolatency_throttle(struct rq_qos *rqos,
|
|||
unsigned use_delay = atomic_read(&lat_to_blkg(iolat)->use_delay);
|
||||
|
||||
if (use_delay)
|
||||
blkcg_schedule_throttle(rqos->q, use_memdelay);
|
||||
blkcg_schedule_throttle(rqos->q->disk, use_memdelay);
|
||||
|
||||
/*
|
||||
* To avoid priority inversions we want to just take a slot if we are
|
||||
|
|
@ -756,8 +756,9 @@ static void blkiolatency_enable_work_fn(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
int blk_iolatency_init(struct request_queue *q)
|
||||
int blk_iolatency_init(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct blk_iolatency *blkiolat;
|
||||
struct rq_qos *rqos;
|
||||
int ret;
|
||||
|
|
|
|||
|
|
@ -202,14 +202,14 @@ void blkcg_set_ioprio(struct bio *bio)
|
|||
bio->bi_ioprio = prio;
|
||||
}
|
||||
|
||||
void blk_ioprio_exit(struct request_queue *q)
|
||||
void blk_ioprio_exit(struct gendisk *disk)
|
||||
{
|
||||
blkcg_deactivate_policy(q, &ioprio_policy);
|
||||
blkcg_deactivate_policy(disk->queue, &ioprio_policy);
|
||||
}
|
||||
|
||||
int blk_ioprio_init(struct request_queue *q)
|
||||
int blk_ioprio_init(struct gendisk *disk)
|
||||
{
|
||||
return blkcg_activate_policy(q, &ioprio_policy);
|
||||
return blkcg_activate_policy(disk->queue, &ioprio_policy);
|
||||
}
|
||||
|
||||
static int __init ioprio_init(void)
|
||||
|
|
|
|||
|
|
@ -9,15 +9,15 @@ struct request_queue;
|
|||
struct bio;
|
||||
|
||||
#ifdef CONFIG_BLK_CGROUP_IOPRIO
|
||||
int blk_ioprio_init(struct request_queue *q);
|
||||
void blk_ioprio_exit(struct request_queue *q);
|
||||
int blk_ioprio_init(struct gendisk *disk);
|
||||
void blk_ioprio_exit(struct gendisk *disk);
|
||||
void blkcg_set_ioprio(struct bio *bio);
|
||||
#else
|
||||
static inline int blk_ioprio_init(struct request_queue *q)
|
||||
static inline int blk_ioprio_init(struct gendisk *disk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void blk_ioprio_exit(struct request_queue *q)
|
||||
static inline void blk_ioprio_exit(struct gendisk *disk)
|
||||
{
|
||||
}
|
||||
static inline void blkcg_set_ioprio(struct bio *bio)
|
||||
|
|
|
|||
172
block/blk-map.c
172
block/blk-map.c
|
|
@ -158,7 +158,7 @@ static int bio_copy_user_iov(struct request *rq, struct rq_map_data *map_data,
|
|||
bio_init(bio, NULL, bio->bi_inline_vecs, nr_pages, req_op(rq));
|
||||
|
||||
if (map_data) {
|
||||
nr_pages = 1 << map_data->page_order;
|
||||
nr_pages = 1U << map_data->page_order;
|
||||
i = map_data->offset / PAGE_SIZE;
|
||||
}
|
||||
while (len) {
|
||||
|
|
@ -231,6 +231,37 @@ out_bmd:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void blk_mq_map_bio_put(struct bio *bio)
|
||||
{
|
||||
if (bio->bi_opf & REQ_ALLOC_CACHE) {
|
||||
bio_put(bio);
|
||||
} else {
|
||||
bio_uninit(bio);
|
||||
kfree(bio);
|
||||
}
|
||||
}
|
||||
|
||||
static struct bio *blk_rq_map_bio_alloc(struct request *rq,
|
||||
unsigned int nr_vecs, gfp_t gfp_mask)
|
||||
{
|
||||
struct bio *bio;
|
||||
|
||||
if (rq->cmd_flags & REQ_POLLED) {
|
||||
blk_opf_t opf = rq->cmd_flags | REQ_ALLOC_CACHE;
|
||||
|
||||
bio = bio_alloc_bioset(NULL, nr_vecs, opf, gfp_mask,
|
||||
&fs_bio_set);
|
||||
if (!bio)
|
||||
return NULL;
|
||||
} else {
|
||||
bio = bio_kmalloc(nr_vecs, gfp_mask);
|
||||
if (!bio)
|
||||
return NULL;
|
||||
bio_init(bio, NULL, bio->bi_inline_vecs, nr_vecs, req_op(rq));
|
||||
}
|
||||
return bio;
|
||||
}
|
||||
|
||||
static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
|
|
@ -243,18 +274,24 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
|
|||
if (!iov_iter_count(iter))
|
||||
return -EINVAL;
|
||||
|
||||
bio = bio_kmalloc(nr_vecs, gfp_mask);
|
||||
if (!bio)
|
||||
bio = blk_rq_map_bio_alloc(rq, nr_vecs, gfp_mask);
|
||||
if (bio == NULL)
|
||||
return -ENOMEM;
|
||||
bio_init(bio, NULL, bio->bi_inline_vecs, nr_vecs, req_op(rq));
|
||||
|
||||
while (iov_iter_count(iter)) {
|
||||
struct page **pages;
|
||||
struct page **pages, *stack_pages[UIO_FASTIOV];
|
||||
ssize_t bytes;
|
||||
size_t offs, added = 0;
|
||||
size_t offs;
|
||||
int npages;
|
||||
|
||||
bytes = iov_iter_get_pages_alloc2(iter, &pages, LONG_MAX, &offs);
|
||||
if (nr_vecs <= ARRAY_SIZE(stack_pages)) {
|
||||
pages = stack_pages;
|
||||
bytes = iov_iter_get_pages2(iter, pages, LONG_MAX,
|
||||
nr_vecs, &offs);
|
||||
} else {
|
||||
bytes = iov_iter_get_pages_alloc2(iter, &pages,
|
||||
LONG_MAX, &offs);
|
||||
}
|
||||
if (unlikely(bytes <= 0)) {
|
||||
ret = bytes ? bytes : -EFAULT;
|
||||
goto out_unmap;
|
||||
|
|
@ -280,7 +317,6 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
|
|||
break;
|
||||
}
|
||||
|
||||
added += n;
|
||||
bytes -= n;
|
||||
offs = 0;
|
||||
}
|
||||
|
|
@ -290,7 +326,8 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
|
|||
*/
|
||||
while (j < npages)
|
||||
put_page(pages[j++]);
|
||||
kvfree(pages);
|
||||
if (pages != stack_pages)
|
||||
kvfree(pages);
|
||||
/* couldn't stuff something into bio? */
|
||||
if (bytes) {
|
||||
iov_iter_revert(iter, bytes);
|
||||
|
|
@ -305,8 +342,7 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
|
|||
|
||||
out_unmap:
|
||||
bio_release_pages(bio, false);
|
||||
bio_uninit(bio);
|
||||
kfree(bio);
|
||||
blk_mq_map_bio_put(bio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -512,6 +548,62 @@ int blk_rq_append_bio(struct request *rq, struct bio *bio)
|
|||
}
|
||||
EXPORT_SYMBOL(blk_rq_append_bio);
|
||||
|
||||
/* Prepare bio for passthrough IO given ITER_BVEC iter */
|
||||
static int blk_rq_map_user_bvec(struct request *rq, const struct iov_iter *iter)
|
||||
{
|
||||
struct request_queue *q = rq->q;
|
||||
size_t nr_iter = iov_iter_count(iter);
|
||||
size_t nr_segs = iter->nr_segs;
|
||||
struct bio_vec *bvecs, *bvprvp = NULL;
|
||||
struct queue_limits *lim = &q->limits;
|
||||
unsigned int nsegs = 0, bytes = 0;
|
||||
struct bio *bio;
|
||||
size_t i;
|
||||
|
||||
if (!nr_iter || (nr_iter >> SECTOR_SHIFT) > queue_max_hw_sectors(q))
|
||||
return -EINVAL;
|
||||
if (nr_segs > queue_max_segments(q))
|
||||
return -EINVAL;
|
||||
|
||||
/* no iovecs to alloc, as we already have a BVEC iterator */
|
||||
bio = blk_rq_map_bio_alloc(rq, 0, GFP_KERNEL);
|
||||
if (bio == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
bio_iov_bvec_set(bio, (struct iov_iter *)iter);
|
||||
blk_rq_bio_prep(rq, bio, nr_segs);
|
||||
|
||||
/* loop to perform a bunch of sanity checks */
|
||||
bvecs = (struct bio_vec *)iter->bvec;
|
||||
for (i = 0; i < nr_segs; i++) {
|
||||
struct bio_vec *bv = &bvecs[i];
|
||||
|
||||
/*
|
||||
* If the queue doesn't support SG gaps and adding this
|
||||
* offset would create a gap, fallback to copy.
|
||||
*/
|
||||
if (bvprvp && bvec_gap_to_prev(lim, bvprvp, bv->bv_offset)) {
|
||||
blk_mq_map_bio_put(bio);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
/* check full condition */
|
||||
if (nsegs >= nr_segs || bytes > UINT_MAX - bv->bv_len)
|
||||
goto put_bio;
|
||||
if (bytes + bv->bv_len > nr_iter)
|
||||
goto put_bio;
|
||||
if (bv->bv_offset + bv->bv_len > PAGE_SIZE)
|
||||
goto put_bio;
|
||||
|
||||
nsegs++;
|
||||
bytes += bv->bv_len;
|
||||
bvprvp = bv;
|
||||
}
|
||||
return 0;
|
||||
put_bio:
|
||||
blk_mq_map_bio_put(bio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_rq_map_user_iov - map user data to a request, for passthrough requests
|
||||
* @q: request queue where request should be inserted
|
||||
|
|
@ -531,24 +623,35 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
|
|||
struct rq_map_data *map_data,
|
||||
const struct iov_iter *iter, gfp_t gfp_mask)
|
||||
{
|
||||
bool copy = false;
|
||||
bool copy = false, map_bvec = false;
|
||||
unsigned long align = q->dma_pad_mask | queue_dma_alignment(q);
|
||||
struct bio *bio = NULL;
|
||||
struct iov_iter i;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!iter_is_iovec(iter))
|
||||
goto fail;
|
||||
|
||||
if (map_data)
|
||||
copy = true;
|
||||
else if (blk_queue_may_bounce(q))
|
||||
copy = true;
|
||||
else if (iov_iter_alignment(iter) & align)
|
||||
copy = true;
|
||||
else if (iov_iter_is_bvec(iter))
|
||||
map_bvec = true;
|
||||
else if (!iter_is_iovec(iter))
|
||||
copy = true;
|
||||
else if (queue_virt_boundary(q))
|
||||
copy = queue_virt_boundary(q) & iov_iter_gap_alignment(iter);
|
||||
|
||||
if (map_bvec) {
|
||||
ret = blk_rq_map_user_bvec(rq, iter);
|
||||
if (!ret)
|
||||
return 0;
|
||||
if (ret != -EREMOTEIO)
|
||||
goto fail;
|
||||
/* fall back to copying the data on limits mismatches */
|
||||
copy = true;
|
||||
}
|
||||
|
||||
i = *iter;
|
||||
do {
|
||||
if (copy)
|
||||
|
|
@ -586,6 +689,42 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
|
|||
}
|
||||
EXPORT_SYMBOL(blk_rq_map_user);
|
||||
|
||||
int blk_rq_map_user_io(struct request *req, struct rq_map_data *map_data,
|
||||
void __user *ubuf, unsigned long buf_len, gfp_t gfp_mask,
|
||||
bool vec, int iov_count, bool check_iter_count, int rw)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (vec) {
|
||||
struct iovec fast_iov[UIO_FASTIOV];
|
||||
struct iovec *iov = fast_iov;
|
||||
struct iov_iter iter;
|
||||
|
||||
ret = import_iovec(rw, ubuf, iov_count ? iov_count : buf_len,
|
||||
UIO_FASTIOV, &iov, &iter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (iov_count) {
|
||||
/* SG_IO howto says that the shorter of the two wins */
|
||||
iov_iter_truncate(&iter, buf_len);
|
||||
if (check_iter_count && !iov_iter_count(&iter)) {
|
||||
kfree(iov);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = blk_rq_map_user_iov(req->q, req, map_data, &iter,
|
||||
gfp_mask);
|
||||
kfree(iov);
|
||||
} else if (buf_len) {
|
||||
ret = blk_rq_map_user(req->q, req, map_data, ubuf, buf_len,
|
||||
gfp_mask);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(blk_rq_map_user_io);
|
||||
|
||||
/**
|
||||
* blk_rq_unmap_user - unmap a request with user data
|
||||
* @bio: start of bio list
|
||||
|
|
@ -611,8 +750,7 @@ int blk_rq_unmap_user(struct bio *bio)
|
|||
|
||||
next_bio = bio;
|
||||
bio = bio->bi_next;
|
||||
bio_uninit(next_bio);
|
||||
kfree(next_bio);
|
||||
blk_mq_map_bio_put(next_bio);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ static int get_first_sibling(unsigned int cpu)
|
|||
return cpu;
|
||||
}
|
||||
|
||||
int blk_mq_map_queues(struct blk_mq_queue_map *qmap)
|
||||
void blk_mq_map_queues(struct blk_mq_queue_map *qmap)
|
||||
{
|
||||
unsigned int *map = qmap->mq_map;
|
||||
unsigned int nr_queues = qmap->nr_queues;
|
||||
|
|
@ -70,8 +70,6 @@ int blk_mq_map_queues(struct blk_mq_queue_map *qmap)
|
|||
map[cpu] = map[first_sibling];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_mq_map_queues);
|
||||
|
||||
|
|
|
|||
|
|
@ -807,8 +807,6 @@ static const char *rq_qos_id_to_name(enum rq_qos_id id)
|
|||
return "latency";
|
||||
case RQ_QOS_COST:
|
||||
return "cost";
|
||||
case RQ_QOS_IOPRIO:
|
||||
return "ioprio";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
* that maps a queue to the CPUs that have irq affinity for the corresponding
|
||||
* vector.
|
||||
*/
|
||||
int blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev,
|
||||
int offset)
|
||||
void blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev,
|
||||
int offset)
|
||||
{
|
||||
const struct cpumask *mask;
|
||||
unsigned int queue, cpu;
|
||||
|
|
@ -38,11 +38,10 @@ int blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev,
|
|||
qmap->mq_map[cpu] = qmap->queue_offset + queue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
fallback:
|
||||
WARN_ON_ONCE(qmap->nr_queues > 1);
|
||||
blk_mq_clear_mq_map(qmap);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_mq_pci_map_queues);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* @set->nr_hw_queues, or @dev does not provide an affinity mask for a
|
||||
* vector, we fallback to the naive mapping.
|
||||
*/
|
||||
int blk_mq_rdma_map_queues(struct blk_mq_queue_map *map,
|
||||
void blk_mq_rdma_map_queues(struct blk_mq_queue_map *map,
|
||||
struct ib_device *dev, int first_vec)
|
||||
{
|
||||
const struct cpumask *mask;
|
||||
|
|
@ -36,9 +36,9 @@ int blk_mq_rdma_map_queues(struct blk_mq_queue_map *map,
|
|||
map->mq_map[cpu] = map->queue_offset + queue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
fallback:
|
||||
return blk_mq_map_queues(map);
|
||||
blk_mq_map_queues(map);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_mq_rdma_map_queues);
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data)
|
|||
* other allocations on previous queue won't be starved.
|
||||
*/
|
||||
if (bt != bt_prev)
|
||||
sbitmap_queue_wake_up(bt_prev);
|
||||
sbitmap_queue_wake_up(bt_prev, 1);
|
||||
|
||||
ws = bt_wait_ptr(bt, data->hctx);
|
||||
} while (1);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* that maps a queue to the CPUs that have irq affinity for the corresponding
|
||||
* vector.
|
||||
*/
|
||||
int blk_mq_virtio_map_queues(struct blk_mq_queue_map *qmap,
|
||||
void blk_mq_virtio_map_queues(struct blk_mq_queue_map *qmap,
|
||||
struct virtio_device *vdev, int first_vec)
|
||||
{
|
||||
const struct cpumask *mask;
|
||||
|
|
@ -39,8 +39,9 @@ int blk_mq_virtio_map_queues(struct blk_mq_queue_map *qmap,
|
|||
qmap->mq_map[cpu] = qmap->queue_offset + queue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
fallback:
|
||||
return blk_mq_map_queues(qmap);
|
||||
blk_mq_map_queues(qmap);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_mq_virtio_map_queues);
|
||||
|
|
|
|||
142
block/blk-mq.c
142
block/blk-mq.c
|
|
@ -510,25 +510,87 @@ retry:
|
|||
alloc_time_ns);
|
||||
}
|
||||
|
||||
struct request *blk_mq_alloc_request(struct request_queue *q, blk_opf_t opf,
|
||||
blk_mq_req_flags_t flags)
|
||||
static struct request *blk_mq_rq_cache_fill(struct request_queue *q,
|
||||
struct blk_plug *plug,
|
||||
blk_opf_t opf,
|
||||
blk_mq_req_flags_t flags)
|
||||
{
|
||||
struct blk_mq_alloc_data data = {
|
||||
.q = q,
|
||||
.flags = flags,
|
||||
.cmd_flags = opf,
|
||||
.nr_tags = 1,
|
||||
.nr_tags = plug->nr_ios,
|
||||
.cached_rq = &plug->cached_rq,
|
||||
};
|
||||
struct request *rq;
|
||||
int ret;
|
||||
|
||||
ret = blk_queue_enter(q, flags);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
if (blk_queue_enter(q, flags))
|
||||
return NULL;
|
||||
|
||||
plug->nr_ios = 1;
|
||||
|
||||
rq = __blk_mq_alloc_requests(&data);
|
||||
if (!rq)
|
||||
goto out_queue_exit;
|
||||
if (unlikely(!rq))
|
||||
blk_queue_exit(q);
|
||||
return rq;
|
||||
}
|
||||
|
||||
static struct request *blk_mq_alloc_cached_request(struct request_queue *q,
|
||||
blk_opf_t opf,
|
||||
blk_mq_req_flags_t flags)
|
||||
{
|
||||
struct blk_plug *plug = current->plug;
|
||||
struct request *rq;
|
||||
|
||||
if (!plug)
|
||||
return NULL;
|
||||
if (rq_list_empty(plug->cached_rq)) {
|
||||
if (plug->nr_ios == 1)
|
||||
return NULL;
|
||||
rq = blk_mq_rq_cache_fill(q, plug, opf, flags);
|
||||
if (rq)
|
||||
goto got_it;
|
||||
return NULL;
|
||||
}
|
||||
rq = rq_list_peek(&plug->cached_rq);
|
||||
if (!rq || rq->q != q)
|
||||
return NULL;
|
||||
|
||||
if (blk_mq_get_hctx_type(opf) != rq->mq_hctx->type)
|
||||
return NULL;
|
||||
if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
|
||||
return NULL;
|
||||
|
||||
plug->cached_rq = rq_list_next(rq);
|
||||
got_it:
|
||||
rq->cmd_flags = opf;
|
||||
INIT_LIST_HEAD(&rq->queuelist);
|
||||
return rq;
|
||||
}
|
||||
|
||||
struct request *blk_mq_alloc_request(struct request_queue *q, blk_opf_t opf,
|
||||
blk_mq_req_flags_t flags)
|
||||
{
|
||||
struct request *rq;
|
||||
|
||||
rq = blk_mq_alloc_cached_request(q, opf, flags);
|
||||
if (!rq) {
|
||||
struct blk_mq_alloc_data data = {
|
||||
.q = q,
|
||||
.flags = flags,
|
||||
.cmd_flags = opf,
|
||||
.nr_tags = 1,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = blk_queue_enter(q, flags);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
rq = __blk_mq_alloc_requests(&data);
|
||||
if (!rq)
|
||||
goto out_queue_exit;
|
||||
}
|
||||
rq->__data_len = 0;
|
||||
rq->__sector = (sector_t) -1;
|
||||
rq->bio = rq->biotail = NULL;
|
||||
|
|
@ -761,8 +823,10 @@ static void blk_complete_request(struct request *req)
|
|||
* can find how many bytes remain in the request
|
||||
* later.
|
||||
*/
|
||||
req->bio = NULL;
|
||||
req->__data_len = 0;
|
||||
if (!req->end_io) {
|
||||
req->bio = NULL;
|
||||
req->__data_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -939,7 +1003,8 @@ inline void __blk_mq_end_request(struct request *rq, blk_status_t error)
|
|||
|
||||
if (rq->end_io) {
|
||||
rq_qos_done(rq->q, rq);
|
||||
rq->end_io(rq, error);
|
||||
if (rq->end_io(rq, error) == RQ_END_IO_FREE)
|
||||
blk_mq_free_request(rq);
|
||||
} else {
|
||||
blk_mq_free_request(rq);
|
||||
}
|
||||
|
|
@ -992,6 +1057,13 @@ void blk_mq_end_request_batch(struct io_comp_batch *iob)
|
|||
|
||||
rq_qos_done(rq->q, rq);
|
||||
|
||||
/*
|
||||
* If end_io handler returns NONE, then it still has
|
||||
* ownership of the request.
|
||||
*/
|
||||
if (rq->end_io && rq->end_io(rq, 0) == RQ_END_IO_NONE)
|
||||
continue;
|
||||
|
||||
WRITE_ONCE(rq->state, MQ_RQ_IDLE);
|
||||
if (!req_ref_put_and_test(rq))
|
||||
continue;
|
||||
|
|
@ -1093,10 +1165,12 @@ bool blk_mq_complete_request_remote(struct request *rq)
|
|||
WRITE_ONCE(rq->state, MQ_RQ_COMPLETE);
|
||||
|
||||
/*
|
||||
* For a polled request, always complete locally, it's pointless
|
||||
* to redirect the completion.
|
||||
* For request which hctx has only one ctx mapping,
|
||||
* or a polled request, always complete locally,
|
||||
* it's pointless to redirect the completion.
|
||||
*/
|
||||
if (rq->cmd_flags & REQ_POLLED)
|
||||
if (rq->mq_hctx->nr_ctx == 1 ||
|
||||
rq->cmd_flags & REQ_POLLED)
|
||||
return false;
|
||||
|
||||
if (blk_mq_complete_need_ipi(rq)) {
|
||||
|
|
@ -1213,6 +1287,12 @@ void blk_execute_rq_nowait(struct request *rq, bool at_head)
|
|||
WARN_ON(!blk_rq_is_passthrough(rq));
|
||||
|
||||
blk_account_io_start(rq);
|
||||
|
||||
/*
|
||||
* As plugging can be enabled for passthrough requests on a zoned
|
||||
* device, directly accessing the plug instead of using blk_mq_plug()
|
||||
* should not have any consequences.
|
||||
*/
|
||||
if (current->plug)
|
||||
blk_add_rq_to_plug(current->plug, rq);
|
||||
else
|
||||
|
|
@ -1225,15 +1305,16 @@ struct blk_rq_wait {
|
|||
blk_status_t ret;
|
||||
};
|
||||
|
||||
static void blk_end_sync_rq(struct request *rq, blk_status_t ret)
|
||||
static enum rq_end_io_ret blk_end_sync_rq(struct request *rq, blk_status_t ret)
|
||||
{
|
||||
struct blk_rq_wait *wait = rq->end_io_data;
|
||||
|
||||
wait->ret = ret;
|
||||
complete(&wait->done);
|
||||
return RQ_END_IO_NONE;
|
||||
}
|
||||
|
||||
static bool blk_rq_is_poll(struct request *rq)
|
||||
bool blk_rq_is_poll(struct request *rq)
|
||||
{
|
||||
if (!rq->mq_hctx)
|
||||
return false;
|
||||
|
|
@ -1243,6 +1324,7 @@ static bool blk_rq_is_poll(struct request *rq)
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_rq_is_poll);
|
||||
|
||||
static void blk_rq_poll_completion(struct request *rq, struct completion *wait)
|
||||
{
|
||||
|
|
@ -1463,10 +1545,12 @@ static bool blk_mq_req_expired(struct request *rq, unsigned long *next)
|
|||
|
||||
void blk_mq_put_rq_ref(struct request *rq)
|
||||
{
|
||||
if (is_flush_rq(rq))
|
||||
rq->end_io(rq, 0);
|
||||
else if (req_ref_put_and_test(rq))
|
||||
if (is_flush_rq(rq)) {
|
||||
if (rq->end_io(rq, 0) == RQ_END_IO_FREE)
|
||||
blk_mq_free_request(rq);
|
||||
} else if (req_ref_put_and_test(rq)) {
|
||||
__blk_mq_free_request(rq);
|
||||
}
|
||||
}
|
||||
|
||||
static bool blk_mq_check_expired(struct request *rq, void *priv)
|
||||
|
|
@ -1992,7 +2076,7 @@ out:
|
|||
if (!needs_restart ||
|
||||
(no_tag && list_empty_careful(&hctx->dispatch_wait.entry)))
|
||||
blk_mq_run_hw_queue(hctx, true);
|
||||
else if (needs_restart && needs_resource)
|
||||
else if (needs_resource)
|
||||
blk_mq_delay_run_hw_queue(hctx, BLK_MQ_RESOURCE_DELAY);
|
||||
|
||||
blk_mq_update_dispatch_busy(hctx, true);
|
||||
|
|
@ -4191,7 +4275,7 @@ static int blk_mq_alloc_set_map_and_rqs(struct blk_mq_tag_set *set)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int blk_mq_update_queue_map(struct blk_mq_tag_set *set)
|
||||
static void blk_mq_update_queue_map(struct blk_mq_tag_set *set)
|
||||
{
|
||||
/*
|
||||
* blk_mq_map_queues() and multiple .map_queues() implementations
|
||||
|
|
@ -4221,10 +4305,10 @@ static int blk_mq_update_queue_map(struct blk_mq_tag_set *set)
|
|||
for (i = 0; i < set->nr_maps; i++)
|
||||
blk_mq_clear_mq_map(&set->map[i]);
|
||||
|
||||
return set->ops->map_queues(set);
|
||||
set->ops->map_queues(set);
|
||||
} else {
|
||||
BUG_ON(set->nr_maps > 1);
|
||||
return blk_mq_map_queues(&set->map[HCTX_TYPE_DEFAULT]);
|
||||
blk_mq_map_queues(&set->map[HCTX_TYPE_DEFAULT]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4323,9 +4407,7 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
|
|||
set->map[i].nr_queues = is_kdump_kernel() ? 1 : set->nr_hw_queues;
|
||||
}
|
||||
|
||||
ret = blk_mq_update_queue_map(set);
|
||||
if (ret)
|
||||
goto out_free_mq_map;
|
||||
blk_mq_update_queue_map(set);
|
||||
|
||||
ret = blk_mq_alloc_set_map_and_rqs(set);
|
||||
if (ret)
|
||||
|
|
@ -4473,14 +4555,14 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
|
|||
list_add(&qe->node, head);
|
||||
|
||||
/*
|
||||
* After elevator_switch_mq, the previous elevator_queue will be
|
||||
* After elevator_switch, the previous elevator_queue will be
|
||||
* released by elevator_release. The reference of the io scheduler
|
||||
* module get by elevator_get will also be put. So we need to get
|
||||
* a reference of the io scheduler module here to prevent it to be
|
||||
* removed.
|
||||
*/
|
||||
__module_get(qe->type->elevator_owner);
|
||||
elevator_switch_mq(q, NULL);
|
||||
elevator_switch(q, NULL);
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
|
||||
return true;
|
||||
|
|
@ -4512,7 +4594,7 @@ static void blk_mq_elv_switch_back(struct list_head *head,
|
|||
kfree(qe);
|
||||
|
||||
mutex_lock(&q->sysfs_lock);
|
||||
elevator_switch_mq(q, t);
|
||||
elevator_switch(q, t);
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -312,7 +312,8 @@ static inline void blk_mq_clear_mq_map(struct blk_mq_queue_map *qmap)
|
|||
static inline struct blk_plug *blk_mq_plug( struct bio *bio)
|
||||
{
|
||||
/* Zoned block device write operation case: do not plug the BIO */
|
||||
if (bdev_is_zoned(bio->bi_bdev) && op_is_write(bio_op(bio)))
|
||||
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
|
||||
bdev_op_is_zoned_write(bio->bi_bdev, bio_op(bio)))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ enum rq_qos_id {
|
|||
RQ_QOS_WBT,
|
||||
RQ_QOS_LATENCY,
|
||||
RQ_QOS_COST,
|
||||
RQ_QOS_IOPRIO,
|
||||
};
|
||||
|
||||
struct rq_wait {
|
||||
|
|
|
|||
|
|
@ -844,7 +844,7 @@ int blk_register_queue(struct gendisk *disk)
|
|||
|
||||
blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);
|
||||
wbt_enable_default(q);
|
||||
blk_throtl_register_queue(q);
|
||||
blk_throtl_register(disk);
|
||||
|
||||
/* Now everything is ready and send out KOBJ_ADD uevent */
|
||||
kobject_uevent(&q->kobj, KOBJ_ADD);
|
||||
|
|
|
|||
|
|
@ -329,8 +329,8 @@ static struct bio *throtl_pop_queued(struct list_head *queued,
|
|||
/* init a service_queue, assumes the caller zeroed it */
|
||||
static void throtl_service_queue_init(struct throtl_service_queue *sq)
|
||||
{
|
||||
INIT_LIST_HEAD(&sq->queued[0]);
|
||||
INIT_LIST_HEAD(&sq->queued[1]);
|
||||
INIT_LIST_HEAD(&sq->queued[READ]);
|
||||
INIT_LIST_HEAD(&sq->queued[WRITE]);
|
||||
sq->pending_tree = RB_ROOT_CACHED;
|
||||
timer_setup(&sq->pending_timer, throtl_pending_timer_fn, 0);
|
||||
}
|
||||
|
|
@ -420,24 +420,17 @@ static void tg_update_has_rules(struct throtl_grp *tg)
|
|||
struct throtl_grp *parent_tg = sq_to_tg(tg->service_queue.parent_sq);
|
||||
struct throtl_data *td = tg->td;
|
||||
int rw;
|
||||
int has_iops_limit = 0;
|
||||
|
||||
for (rw = READ; rw <= WRITE; rw++) {
|
||||
unsigned int iops_limit = tg_iops_limit(tg, rw);
|
||||
|
||||
tg->has_rules[rw] = (parent_tg && parent_tg->has_rules[rw]) ||
|
||||
tg->has_rules_iops[rw] =
|
||||
(parent_tg && parent_tg->has_rules_iops[rw]) ||
|
||||
(td->limit_valid[td->limit_index] &&
|
||||
(tg_bps_limit(tg, rw) != U64_MAX ||
|
||||
iops_limit != UINT_MAX));
|
||||
|
||||
if (iops_limit != UINT_MAX)
|
||||
has_iops_limit = 1;
|
||||
tg_iops_limit(tg, rw) != UINT_MAX);
|
||||
tg->has_rules_bps[rw] =
|
||||
(parent_tg && parent_tg->has_rules_bps[rw]) ||
|
||||
(td->limit_valid[td->limit_index] &&
|
||||
(tg_bps_limit(tg, rw) != U64_MAX));
|
||||
}
|
||||
|
||||
if (has_iops_limit)
|
||||
tg->flags |= THROTL_TG_HAS_IOPS_LIMIT;
|
||||
else
|
||||
tg->flags &= ~THROTL_TG_HAS_IOPS_LIMIT;
|
||||
}
|
||||
|
||||
static void throtl_pd_online(struct blkg_policy_data *pd)
|
||||
|
|
@ -520,7 +513,6 @@ static void throtl_rb_erase(struct rb_node *n,
|
|||
{
|
||||
rb_erase_cached(n, &parent_sq->pending_tree);
|
||||
RB_CLEAR_NODE(n);
|
||||
--parent_sq->nr_pending;
|
||||
}
|
||||
|
||||
static void update_min_dispatch_time(struct throtl_service_queue *parent_sq)
|
||||
|
|
@ -572,7 +564,11 @@ static void throtl_enqueue_tg(struct throtl_grp *tg)
|
|||
static void throtl_dequeue_tg(struct throtl_grp *tg)
|
||||
{
|
||||
if (tg->flags & THROTL_TG_PENDING) {
|
||||
throtl_rb_erase(&tg->rb_node, tg->service_queue.parent_sq);
|
||||
struct throtl_service_queue *parent_sq =
|
||||
tg->service_queue.parent_sq;
|
||||
|
||||
throtl_rb_erase(&tg->rb_node, parent_sq);
|
||||
--parent_sq->nr_pending;
|
||||
tg->flags &= ~THROTL_TG_PENDING;
|
||||
}
|
||||
}
|
||||
|
|
@ -639,6 +635,8 @@ static inline void throtl_start_new_slice_with_credit(struct throtl_grp *tg,
|
|||
{
|
||||
tg->bytes_disp[rw] = 0;
|
||||
tg->io_disp[rw] = 0;
|
||||
tg->carryover_bytes[rw] = 0;
|
||||
tg->carryover_ios[rw] = 0;
|
||||
|
||||
/*
|
||||
* Previous slice has expired. We must have trimmed it after last
|
||||
|
|
@ -656,12 +654,17 @@ static inline void throtl_start_new_slice_with_credit(struct throtl_grp *tg,
|
|||
tg->slice_end[rw], jiffies);
|
||||
}
|
||||
|
||||
static inline void throtl_start_new_slice(struct throtl_grp *tg, bool rw)
|
||||
static inline void throtl_start_new_slice(struct throtl_grp *tg, bool rw,
|
||||
bool clear_carryover)
|
||||
{
|
||||
tg->bytes_disp[rw] = 0;
|
||||
tg->io_disp[rw] = 0;
|
||||
tg->slice_start[rw] = jiffies;
|
||||
tg->slice_end[rw] = jiffies + tg->td->throtl_slice;
|
||||
if (clear_carryover) {
|
||||
tg->carryover_bytes[rw] = 0;
|
||||
tg->carryover_ios[rw] = 0;
|
||||
}
|
||||
|
||||
throtl_log(&tg->service_queue,
|
||||
"[%c] new slice start=%lu end=%lu jiffies=%lu",
|
||||
|
|
@ -754,13 +757,76 @@ static inline void throtl_trim_slice(struct throtl_grp *tg, bool rw)
|
|||
tg->slice_start[rw], tg->slice_end[rw], jiffies);
|
||||
}
|
||||
|
||||
static bool tg_with_in_iops_limit(struct throtl_grp *tg, struct bio *bio,
|
||||
u32 iops_limit, unsigned long *wait)
|
||||
static unsigned int calculate_io_allowed(u32 iops_limit,
|
||||
unsigned long jiffy_elapsed)
|
||||
{
|
||||
unsigned int io_allowed;
|
||||
u64 tmp;
|
||||
|
||||
/*
|
||||
* jiffy_elapsed should not be a big value as minimum iops can be
|
||||
* 1 then at max jiffy elapsed should be equivalent of 1 second as we
|
||||
* will allow dispatch after 1 second and after that slice should
|
||||
* have been trimmed.
|
||||
*/
|
||||
|
||||
tmp = (u64)iops_limit * jiffy_elapsed;
|
||||
do_div(tmp, HZ);
|
||||
|
||||
if (tmp > UINT_MAX)
|
||||
io_allowed = UINT_MAX;
|
||||
else
|
||||
io_allowed = tmp;
|
||||
|
||||
return io_allowed;
|
||||
}
|
||||
|
||||
static u64 calculate_bytes_allowed(u64 bps_limit, unsigned long jiffy_elapsed)
|
||||
{
|
||||
return mul_u64_u64_div_u64(bps_limit, (u64)jiffy_elapsed, (u64)HZ);
|
||||
}
|
||||
|
||||
static void __tg_update_carryover(struct throtl_grp *tg, bool rw)
|
||||
{
|
||||
unsigned long jiffy_elapsed = jiffies - tg->slice_start[rw];
|
||||
u64 bps_limit = tg_bps_limit(tg, rw);
|
||||
u32 iops_limit = tg_iops_limit(tg, rw);
|
||||
|
||||
/*
|
||||
* If config is updated while bios are still throttled, calculate and
|
||||
* accumulate how many bytes/ios are waited across changes. And
|
||||
* carryover_bytes/ios will be used to calculate new wait time under new
|
||||
* configuration.
|
||||
*/
|
||||
if (bps_limit != U64_MAX)
|
||||
tg->carryover_bytes[rw] +=
|
||||
calculate_bytes_allowed(bps_limit, jiffy_elapsed) -
|
||||
tg->bytes_disp[rw];
|
||||
if (iops_limit != UINT_MAX)
|
||||
tg->carryover_ios[rw] +=
|
||||
calculate_io_allowed(iops_limit, jiffy_elapsed) -
|
||||
tg->io_disp[rw];
|
||||
}
|
||||
|
||||
static void tg_update_carryover(struct throtl_grp *tg)
|
||||
{
|
||||
if (tg->service_queue.nr_queued[READ])
|
||||
__tg_update_carryover(tg, READ);
|
||||
if (tg->service_queue.nr_queued[WRITE])
|
||||
__tg_update_carryover(tg, WRITE);
|
||||
|
||||
/* see comments in struct throtl_grp for meaning of these fields. */
|
||||
throtl_log(&tg->service_queue, "%s: %llu %llu %u %u\n", __func__,
|
||||
tg->carryover_bytes[READ], tg->carryover_bytes[WRITE],
|
||||
tg->carryover_ios[READ], tg->carryover_ios[WRITE]);
|
||||
}
|
||||
|
||||
static bool tg_within_iops_limit(struct throtl_grp *tg, struct bio *bio,
|
||||
u32 iops_limit, unsigned long *wait)
|
||||
{
|
||||
bool rw = bio_data_dir(bio);
|
||||
unsigned int io_allowed;
|
||||
unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
|
||||
u64 tmp;
|
||||
|
||||
if (iops_limit == UINT_MAX) {
|
||||
if (wait)
|
||||
|
|
@ -772,22 +838,8 @@ static bool tg_with_in_iops_limit(struct throtl_grp *tg, struct bio *bio,
|
|||
|
||||
/* Round up to the next throttle slice, wait time must be nonzero */
|
||||
jiffy_elapsed_rnd = roundup(jiffy_elapsed + 1, tg->td->throtl_slice);
|
||||
|
||||
/*
|
||||
* jiffy_elapsed_rnd should not be a big value as minimum iops can be
|
||||
* 1 then at max jiffy elapsed should be equivalent of 1 second as we
|
||||
* will allow dispatch after 1 second and after that slice should
|
||||
* have been trimmed.
|
||||
*/
|
||||
|
||||
tmp = (u64)iops_limit * jiffy_elapsed_rnd;
|
||||
do_div(tmp, HZ);
|
||||
|
||||
if (tmp > UINT_MAX)
|
||||
io_allowed = UINT_MAX;
|
||||
else
|
||||
io_allowed = tmp;
|
||||
|
||||
io_allowed = calculate_io_allowed(iops_limit, jiffy_elapsed_rnd) +
|
||||
tg->carryover_ios[rw];
|
||||
if (tg->io_disp[rw] + 1 <= io_allowed) {
|
||||
if (wait)
|
||||
*wait = 0;
|
||||
|
|
@ -802,16 +854,16 @@ static bool tg_with_in_iops_limit(struct throtl_grp *tg, struct bio *bio,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool tg_with_in_bps_limit(struct throtl_grp *tg, struct bio *bio,
|
||||
u64 bps_limit, unsigned long *wait)
|
||||
static bool tg_within_bps_limit(struct throtl_grp *tg, struct bio *bio,
|
||||
u64 bps_limit, unsigned long *wait)
|
||||
{
|
||||
bool rw = bio_data_dir(bio);
|
||||
u64 bytes_allowed, extra_bytes, tmp;
|
||||
u64 bytes_allowed, extra_bytes;
|
||||
unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
|
||||
unsigned int bio_size = throtl_bio_data_size(bio);
|
||||
|
||||
/* no need to throttle if this bio's bytes have been accounted */
|
||||
if (bps_limit == U64_MAX || bio_flagged(bio, BIO_THROTTLED)) {
|
||||
if (bps_limit == U64_MAX || bio_flagged(bio, BIO_BPS_THROTTLED)) {
|
||||
if (wait)
|
||||
*wait = 0;
|
||||
return true;
|
||||
|
|
@ -824,11 +876,8 @@ static bool tg_with_in_bps_limit(struct throtl_grp *tg, struct bio *bio,
|
|||
jiffy_elapsed_rnd = tg->td->throtl_slice;
|
||||
|
||||
jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, tg->td->throtl_slice);
|
||||
|
||||
tmp = bps_limit * jiffy_elapsed_rnd;
|
||||
do_div(tmp, HZ);
|
||||
bytes_allowed = tmp;
|
||||
|
||||
bytes_allowed = calculate_bytes_allowed(bps_limit, jiffy_elapsed_rnd) +
|
||||
tg->carryover_bytes[rw];
|
||||
if (tg->bytes_disp[rw] + bio_size <= bytes_allowed) {
|
||||
if (wait)
|
||||
*wait = 0;
|
||||
|
|
@ -889,7 +938,7 @@ static bool tg_may_dispatch(struct throtl_grp *tg, struct bio *bio,
|
|||
* slice and it should be extended instead.
|
||||
*/
|
||||
if (throtl_slice_used(tg, rw) && !(tg->service_queue.nr_queued[rw]))
|
||||
throtl_start_new_slice(tg, rw);
|
||||
throtl_start_new_slice(tg, rw, true);
|
||||
else {
|
||||
if (time_before(tg->slice_end[rw],
|
||||
jiffies + tg->td->throtl_slice))
|
||||
|
|
@ -897,8 +946,8 @@ static bool tg_may_dispatch(struct throtl_grp *tg, struct bio *bio,
|
|||
jiffies + tg->td->throtl_slice);
|
||||
}
|
||||
|
||||
if (tg_with_in_bps_limit(tg, bio, bps_limit, &bps_wait) &&
|
||||
tg_with_in_iops_limit(tg, bio, iops_limit, &iops_wait)) {
|
||||
if (tg_within_bps_limit(tg, bio, bps_limit, &bps_wait) &&
|
||||
tg_within_iops_limit(tg, bio, iops_limit, &iops_wait)) {
|
||||
if (wait)
|
||||
*wait = 0;
|
||||
return true;
|
||||
|
|
@ -921,22 +970,13 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
|
|||
unsigned int bio_size = throtl_bio_data_size(bio);
|
||||
|
||||
/* Charge the bio to the group */
|
||||
if (!bio_flagged(bio, BIO_THROTTLED)) {
|
||||
if (!bio_flagged(bio, BIO_BPS_THROTTLED)) {
|
||||
tg->bytes_disp[rw] += bio_size;
|
||||
tg->last_bytes_disp[rw] += bio_size;
|
||||
}
|
||||
|
||||
tg->io_disp[rw]++;
|
||||
tg->last_io_disp[rw]++;
|
||||
|
||||
/*
|
||||
* BIO_THROTTLED is used to prevent the same bio to be throttled
|
||||
* more than once as a throttled bio will go through blk-throtl the
|
||||
* second time when it eventually gets issued. Set it when a bio
|
||||
* is being charged to a tg.
|
||||
*/
|
||||
if (!bio_flagged(bio, BIO_THROTTLED))
|
||||
bio_set_flag(bio, BIO_THROTTLED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -990,9 +1030,9 @@ static void tg_update_disptime(struct throtl_grp *tg)
|
|||
disptime = jiffies + min_wait;
|
||||
|
||||
/* Update dispatch time */
|
||||
throtl_dequeue_tg(tg);
|
||||
throtl_rb_erase(&tg->rb_node, tg->service_queue.parent_sq);
|
||||
tg->disptime = disptime;
|
||||
throtl_enqueue_tg(tg);
|
||||
tg_service_queue_add(tg);
|
||||
|
||||
/* see throtl_add_bio_tg() */
|
||||
tg->flags &= ~THROTL_TG_WAS_EMPTY;
|
||||
|
|
@ -1026,6 +1066,7 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw)
|
|||
sq->nr_queued[rw]--;
|
||||
|
||||
throtl_charge_bio(tg, bio);
|
||||
bio_set_flag(bio, BIO_BPS_THROTTLED);
|
||||
|
||||
/*
|
||||
* If our parent is another tg, we just need to transfer @bio to
|
||||
|
|
@ -1101,13 +1142,13 @@ static int throtl_select_dispatch(struct throtl_service_queue *parent_sq)
|
|||
if (time_before(jiffies, tg->disptime))
|
||||
break;
|
||||
|
||||
throtl_dequeue_tg(tg);
|
||||
|
||||
nr_disp += throtl_dispatch_tg(tg);
|
||||
|
||||
sq = &tg->service_queue;
|
||||
if (sq->nr_queued[0] || sq->nr_queued[1])
|
||||
if (sq->nr_queued[READ] || sq->nr_queued[WRITE])
|
||||
tg_update_disptime(tg);
|
||||
else
|
||||
throtl_dequeue_tg(tg);
|
||||
|
||||
if (nr_disp >= THROTL_QUANTUM)
|
||||
break;
|
||||
|
|
@ -1321,8 +1362,8 @@ static void tg_conf_updated(struct throtl_grp *tg, bool global)
|
|||
* that a group's limit are dropped suddenly and we don't want to
|
||||
* account recently dispatched IO with new low rate.
|
||||
*/
|
||||
throtl_start_new_slice(tg, READ);
|
||||
throtl_start_new_slice(tg, WRITE);
|
||||
throtl_start_new_slice(tg, READ, false);
|
||||
throtl_start_new_slice(tg, WRITE, false);
|
||||
|
||||
if (tg->flags & THROTL_TG_PENDING) {
|
||||
tg_update_disptime(tg);
|
||||
|
|
@ -1350,6 +1391,7 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of,
|
|||
v = U64_MAX;
|
||||
|
||||
tg = blkg_to_tg(ctx.blkg);
|
||||
tg_update_carryover(tg);
|
||||
|
||||
if (is_u64)
|
||||
*(u64 *)((void *)tg + of_cft(of)->private) = v;
|
||||
|
|
@ -1536,6 +1578,7 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
|
|||
return ret;
|
||||
|
||||
tg = blkg_to_tg(ctx.blkg);
|
||||
tg_update_carryover(tg);
|
||||
|
||||
v[0] = tg->bps_conf[READ][index];
|
||||
v[1] = tg->bps_conf[WRITE][index];
|
||||
|
|
@ -1673,6 +1716,41 @@ struct blkcg_policy blkcg_policy_throtl = {
|
|||
.pd_free_fn = throtl_pd_free,
|
||||
};
|
||||
|
||||
void blk_throtl_cancel_bios(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct cgroup_subsys_state *pos_css;
|
||||
struct blkcg_gq *blkg;
|
||||
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
/*
|
||||
* queue_lock is held, rcu lock is not needed here technically.
|
||||
* However, rcu lock is still held to emphasize that following
|
||||
* path need RCU protection and to prevent warning from lockdep.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
blkg_for_each_descendant_post(blkg, pos_css, q->root_blkg) {
|
||||
struct throtl_grp *tg = blkg_to_tg(blkg);
|
||||
struct throtl_service_queue *sq = &tg->service_queue;
|
||||
|
||||
/*
|
||||
* Set the flag to make sure throtl_pending_timer_fn() won't
|
||||
* stop until all throttled bios are dispatched.
|
||||
*/
|
||||
blkg_to_tg(blkg)->flags |= THROTL_TG_CANCELING;
|
||||
/*
|
||||
* Update disptime after setting the above flag to make sure
|
||||
* throtl_select_dispatch() won't exit without dispatching.
|
||||
*/
|
||||
tg_update_disptime(tg);
|
||||
|
||||
throtl_schedule_pending_timer(sq, jiffies + 1);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_THROTTLING_LOW
|
||||
static unsigned long __tg_last_low_overflow_time(struct throtl_grp *tg)
|
||||
{
|
||||
unsigned long rtime = jiffies, wtime = jiffies;
|
||||
|
|
@ -1777,39 +1855,6 @@ static bool throtl_hierarchy_can_upgrade(struct throtl_grp *tg)
|
|||
return false;
|
||||
}
|
||||
|
||||
void blk_throtl_cancel_bios(struct request_queue *q)
|
||||
{
|
||||
struct cgroup_subsys_state *pos_css;
|
||||
struct blkcg_gq *blkg;
|
||||
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
/*
|
||||
* queue_lock is held, rcu lock is not needed here technically.
|
||||
* However, rcu lock is still held to emphasize that following
|
||||
* path need RCU protection and to prevent warning from lockdep.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
blkg_for_each_descendant_post(blkg, pos_css, q->root_blkg) {
|
||||
struct throtl_grp *tg = blkg_to_tg(blkg);
|
||||
struct throtl_service_queue *sq = &tg->service_queue;
|
||||
|
||||
/*
|
||||
* Set the flag to make sure throtl_pending_timer_fn() won't
|
||||
* stop until all throttled bios are dispatched.
|
||||
*/
|
||||
blkg_to_tg(blkg)->flags |= THROTL_TG_CANCELING;
|
||||
/*
|
||||
* Update disptime after setting the above flag to make sure
|
||||
* throtl_select_dispatch() won't exit without dispatching.
|
||||
*/
|
||||
tg_update_disptime(tg);
|
||||
|
||||
throtl_schedule_pending_timer(sq, jiffies + 1);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
}
|
||||
|
||||
static bool throtl_can_upgrade(struct throtl_data *td,
|
||||
struct throtl_grp *this_tg)
|
||||
{
|
||||
|
|
@ -2005,7 +2050,6 @@ static void blk_throtl_update_idletime(struct throtl_grp *tg)
|
|||
tg->checked_last_finish_time = last_finish_time;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_THROTTLING_LOW
|
||||
static void throtl_update_latency_buckets(struct throtl_data *td)
|
||||
{
|
||||
struct avg_latency_bucket avg_latency[2][LATENCY_BUCKET_SIZE];
|
||||
|
|
@ -2086,6 +2130,28 @@ static void throtl_update_latency_buckets(struct throtl_data *td)
|
|||
static inline void throtl_update_latency_buckets(struct throtl_data *td)
|
||||
{
|
||||
}
|
||||
|
||||
static void blk_throtl_update_idletime(struct throtl_grp *tg)
|
||||
{
|
||||
}
|
||||
|
||||
static void throtl_downgrade_check(struct throtl_grp *tg)
|
||||
{
|
||||
}
|
||||
|
||||
static void throtl_upgrade_check(struct throtl_grp *tg)
|
||||
{
|
||||
}
|
||||
|
||||
static bool throtl_can_upgrade(struct throtl_data *td,
|
||||
struct throtl_grp *this_tg)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void throtl_upgrade_state(struct throtl_data *td)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
bool __blk_throtl_bio(struct bio *bio)
|
||||
|
|
@ -2159,8 +2225,10 @@ again:
|
|||
qn = &tg->qnode_on_parent[rw];
|
||||
sq = sq->parent_sq;
|
||||
tg = sq_to_tg(sq);
|
||||
if (!tg)
|
||||
if (!tg) {
|
||||
bio_set_flag(bio, BIO_BPS_THROTTLED);
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
/* out-of-limit, queue to @tg */
|
||||
|
|
@ -2189,8 +2257,6 @@ again:
|
|||
}
|
||||
|
||||
out_unlock:
|
||||
bio_set_flag(bio, BIO_THROTTLED);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_THROTTLING_LOW
|
||||
if (throttled || !td->track_bio_latency)
|
||||
bio->bi_issue.value |= BIO_ISSUE_THROTL_SKIP_LATENCY;
|
||||
|
|
@ -2286,8 +2352,9 @@ void blk_throtl_bio_endio(struct bio *bio)
|
|||
}
|
||||
#endif
|
||||
|
||||
int blk_throtl_init(struct request_queue *q)
|
||||
int blk_throtl_init(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct throtl_data *td;
|
||||
int ret;
|
||||
|
||||
|
|
@ -2329,8 +2396,10 @@ int blk_throtl_init(struct request_queue *q)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void blk_throtl_exit(struct request_queue *q)
|
||||
void blk_throtl_exit(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
|
||||
BUG_ON(!q->td);
|
||||
del_timer_sync(&q->td->service_queue.pending_timer);
|
||||
throtl_shutdown_wq(q);
|
||||
|
|
@ -2340,8 +2409,9 @@ void blk_throtl_exit(struct request_queue *q)
|
|||
kfree(q->td);
|
||||
}
|
||||
|
||||
void blk_throtl_register_queue(struct request_queue *q)
|
||||
void blk_throtl_register(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct throtl_data *td;
|
||||
int i;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,7 @@ struct throtl_service_queue {
|
|||
enum tg_state_flags {
|
||||
THROTL_TG_PENDING = 1 << 0, /* on parent's pending tree */
|
||||
THROTL_TG_WAS_EMPTY = 1 << 1, /* bio_lists[] became non-empty */
|
||||
THROTL_TG_HAS_IOPS_LIMIT = 1 << 2, /* tg has iops limit */
|
||||
THROTL_TG_CANCELING = 1 << 3, /* starts to cancel bio */
|
||||
THROTL_TG_CANCELING = 1 << 2, /* starts to cancel bio */
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -99,7 +98,8 @@ struct throtl_grp {
|
|||
unsigned int flags;
|
||||
|
||||
/* are there any throtl rules between this group and td? */
|
||||
bool has_rules[2];
|
||||
bool has_rules_bps[2];
|
||||
bool has_rules_iops[2];
|
||||
|
||||
/* internally used bytes per second rate limits */
|
||||
uint64_t bps[2][LIMIT_CNT];
|
||||
|
|
@ -121,6 +121,15 @@ struct throtl_grp {
|
|||
uint64_t last_bytes_disp[2];
|
||||
unsigned int last_io_disp[2];
|
||||
|
||||
/*
|
||||
* The following two fields are updated when new configuration is
|
||||
* submitted while some bios are still throttled, they record how many
|
||||
* bytes/ios are waited already in previous configuration, and they will
|
||||
* be used to calculate wait time under new configuration.
|
||||
*/
|
||||
uint64_t carryover_bytes[2];
|
||||
unsigned int carryover_ios[2];
|
||||
|
||||
unsigned long last_check_time;
|
||||
|
||||
unsigned long latency_target; /* us */
|
||||
|
|
@ -159,27 +168,37 @@ static inline struct throtl_grp *blkg_to_tg(struct blkcg_gq *blkg)
|
|||
* Internal throttling interface
|
||||
*/
|
||||
#ifndef CONFIG_BLK_DEV_THROTTLING
|
||||
static inline int blk_throtl_init(struct request_queue *q) { return 0; }
|
||||
static inline void blk_throtl_exit(struct request_queue *q) { }
|
||||
static inline void blk_throtl_register_queue(struct request_queue *q) { }
|
||||
static inline int blk_throtl_init(struct gendisk *disk) { return 0; }
|
||||
static inline void blk_throtl_exit(struct gendisk *disk) { }
|
||||
static inline void blk_throtl_register(struct gendisk *disk) { }
|
||||
static inline bool blk_throtl_bio(struct bio *bio) { return false; }
|
||||
static inline void blk_throtl_cancel_bios(struct request_queue *q) { }
|
||||
static inline void blk_throtl_cancel_bios(struct gendisk *disk) { }
|
||||
#else /* CONFIG_BLK_DEV_THROTTLING */
|
||||
int blk_throtl_init(struct request_queue *q);
|
||||
void blk_throtl_exit(struct request_queue *q);
|
||||
void blk_throtl_register_queue(struct request_queue *q);
|
||||
int blk_throtl_init(struct gendisk *disk);
|
||||
void blk_throtl_exit(struct gendisk *disk);
|
||||
void blk_throtl_register(struct gendisk *disk);
|
||||
bool __blk_throtl_bio(struct bio *bio);
|
||||
void blk_throtl_cancel_bios(struct request_queue *q);
|
||||
static inline bool blk_throtl_bio(struct bio *bio)
|
||||
void blk_throtl_cancel_bios(struct gendisk *disk);
|
||||
|
||||
static inline bool blk_should_throtl(struct bio *bio)
|
||||
{
|
||||
struct throtl_grp *tg = blkg_to_tg(bio->bi_blkg);
|
||||
int rw = bio_data_dir(bio);
|
||||
|
||||
/* no need to throttle bps any more if the bio has been throttled */
|
||||
if (bio_flagged(bio, BIO_THROTTLED) &&
|
||||
!(tg->flags & THROTL_TG_HAS_IOPS_LIMIT))
|
||||
return false;
|
||||
/* iops limit is always counted */
|
||||
if (tg->has_rules_iops[rw])
|
||||
return true;
|
||||
|
||||
if (!tg->has_rules[bio_data_dir(bio)])
|
||||
if (tg->has_rules_bps[rw] && !bio_flagged(bio, BIO_BPS_THROTTLED))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool blk_throtl_bio(struct bio *bio)
|
||||
{
|
||||
|
||||
if (!blk_should_throtl(bio))
|
||||
return false;
|
||||
|
||||
return __blk_throtl_bio(bio);
|
||||
|
|
|
|||
|
|
@ -843,6 +843,10 @@ int wbt_init(struct request_queue *q)
|
|||
rwb->enable_state = WBT_STATE_ON_DEFAULT;
|
||||
rwb->wc = 1;
|
||||
rwb->rq_depth.default_depth = RWB_DEF_DEPTH;
|
||||
rwb->min_lat_nsec = wbt_default_latency_nsec(q);
|
||||
|
||||
wbt_queue_depth_changed(&rwb->rqos);
|
||||
wbt_set_write_cache(q, test_bit(QUEUE_FLAG_WC, &q->queue_flags));
|
||||
|
||||
/*
|
||||
* Assign rwb and add the stats callback.
|
||||
|
|
@ -853,11 +857,6 @@ int wbt_init(struct request_queue *q)
|
|||
|
||||
blk_stat_add_callback(q, rwb->cb);
|
||||
|
||||
rwb->min_lat_nsec = wbt_default_latency_nsec(q);
|
||||
|
||||
wbt_queue_depth_changed(&rwb->rqos);
|
||||
wbt_set_write_cache(q, test_bit(QUEUE_FLAG_WC, &q->queue_flags));
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
|
|
|
|||
|
|
@ -63,13 +63,10 @@ bool blk_req_needs_zone_write_lock(struct request *rq)
|
|||
if (!rq->q->disk->seq_zones_wlock)
|
||||
return false;
|
||||
|
||||
switch (req_op(rq)) {
|
||||
case REQ_OP_WRITE_ZEROES:
|
||||
case REQ_OP_WRITE:
|
||||
if (bdev_op_is_zoned_write(rq->q->disk->part0, req_op(rq)))
|
||||
return blk_rq_zone_is_seq(rq);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_req_needs_zone_write_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -270,8 +270,7 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list,
|
|||
|
||||
void blk_insert_flush(struct request *rq);
|
||||
|
||||
int elevator_switch_mq(struct request_queue *q,
|
||||
struct elevator_type *new_e);
|
||||
int elevator_switch(struct request_queue *q, struct elevator_type *new_e);
|
||||
void elevator_exit(struct request_queue *q);
|
||||
int elv_register_queue(struct request_queue *q, bool uevent);
|
||||
void elv_unregister_queue(struct request_queue *q);
|
||||
|
|
@ -389,9 +388,9 @@ static inline struct bio *blk_queue_bounce(struct bio *bio,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_BLK_CGROUP_IOLATENCY
|
||||
extern int blk_iolatency_init(struct request_queue *q);
|
||||
int blk_iolatency_init(struct gendisk *disk);
|
||||
#else
|
||||
static inline int blk_iolatency_init(struct request_queue *q) { return 0; }
|
||||
static inline int blk_iolatency_init(struct gendisk *disk) { return 0; };
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
|
|
|
|||
|
|
@ -588,7 +588,7 @@ void elv_unregister(struct elevator_type *e)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(elv_unregister);
|
||||
|
||||
int elevator_switch_mq(struct request_queue *q,
|
||||
static int elevator_switch_mq(struct request_queue *q,
|
||||
struct elevator_type *new_e)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -723,7 +723,7 @@ void elevator_init_mq(struct request_queue *q)
|
|||
* need for the new one. this way we have a chance of going back to the old
|
||||
* one, if the new one fails init for some reason.
|
||||
*/
|
||||
static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
|
||||
int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue