mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 11:06:41 -05:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-6.17-rc2). No conflicts. Adjacent changes: drivers/net/ethernet/stmicro/stmmac/dwmac-rk.cd7a276a576("net: stmmac: rk: convert to suspend()/resume() methods")de1e963ad0("net: stmmac: rk: put the PHY clock on remove") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -36,3 +36,10 @@ Description: Displays the content of the Runtime Configuration Interface
|
||||
Table version 2 on Dell EMC PowerEdge systems in binary format
|
||||
Users: It is used by Dell EMC OpenManage Server Administrator tool to
|
||||
populate BIOS setup page.
|
||||
|
||||
What: /sys/firmware/efi/ovmf_debug_log
|
||||
Date: July 2025
|
||||
Contact: Gerd Hoffmann <kraxel@redhat.com>, linux-efi@vger.kernel.org
|
||||
Description: Displays the content of the OVMF debug log buffer. The file is
|
||||
only present in case the firmware supports logging to a memory
|
||||
buffer.
|
||||
|
||||
@@ -68,13 +68,13 @@ examples:
|
||||
#include <dt-bindings/reset/sun8i-h3-ccu.h>
|
||||
|
||||
msgbox: mailbox@1c17000 {
|
||||
compatible = "allwinner,sun8i-h3-msgbox",
|
||||
"allwinner,sun6i-a31-msgbox";
|
||||
reg = <0x01c17000 0x1000>;
|
||||
clocks = <&ccu CLK_BUS_MSGBOX>;
|
||||
resets = <&ccu RST_BUS_MSGBOX>;
|
||||
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#mbox-cells = <1>;
|
||||
compatible = "allwinner,sun8i-h3-msgbox",
|
||||
"allwinner,sun6i-a31-msgbox";
|
||||
reg = <0x01c17000 0x1000>;
|
||||
clocks = <&ccu CLK_BUS_MSGBOX>;
|
||||
resets = <&ccu RST_BUS_MSGBOX>;
|
||||
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#mbox-cells = <1>;
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
@@ -27,7 +27,7 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
description:
|
||||
Contains the interrupt information corresponding to each of the 3 links
|
||||
of MHU.
|
||||
@@ -46,8 +46,8 @@ additionalProperties: false
|
||||
examples:
|
||||
- |
|
||||
mailbox@c883c404 {
|
||||
compatible = "amlogic,meson-gxbb-mhu";
|
||||
reg = <0xc883c404 0x4c>;
|
||||
interrupts = <208>, <209>, <210>;
|
||||
#mbox-cells = <1>;
|
||||
compatible = "amlogic,meson-gxbb-mhu";
|
||||
reg = <0xc883c404 0x4c>;
|
||||
interrupts = <208>, <209>, <210>;
|
||||
#mbox-cells = <1>;
|
||||
};
|
||||
|
||||
@@ -78,11 +78,11 @@ additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
mailbox@77408000 {
|
||||
compatible = "apple,t8103-asc-mailbox", "apple,asc-mailbox-v4";
|
||||
reg = <0x77408000 0x4000>;
|
||||
interrupts = <1 583 4>, <1 584 4>, <1 585 4>, <1 586 4>;
|
||||
interrupt-names = "send-empty", "send-not-empty",
|
||||
"recv-empty", "recv-not-empty";
|
||||
#mbox-cells = <0>;
|
||||
};
|
||||
mailbox@77408000 {
|
||||
compatible = "apple,t8103-asc-mailbox", "apple,asc-mailbox-v4";
|
||||
reg = <0x77408000 0x4000>;
|
||||
interrupts = <1 583 4>, <1 584 4>, <1 585 4>, <1 586 4>;
|
||||
interrupt-names = "send-empty", "send-not-empty",
|
||||
"recv-empty", "recv-not-empty";
|
||||
#mbox-cells = <0>;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mailbox/aspeed,ast2700-mailbox.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ASPEED AST2700 mailbox controller
|
||||
|
||||
maintainers:
|
||||
- Jammy Huang <jammy_huang@aspeedtech.com>
|
||||
|
||||
description: >
|
||||
ASPEED AST2700 has multiple processors that need to communicate with each
|
||||
other. The mailbox controller provides a way for these processors to send
|
||||
messages to each other. It is a hardware-based inter-processor communication
|
||||
mechanism that allows processors to send and receive messages through
|
||||
dedicated channels.
|
||||
|
||||
The mailbox's tx/rx are independent, meaning that one processor can send a
|
||||
message while another processor is receiving a message simultaneously.
|
||||
There are 4 channels available for both tx and rx operations. Each channel
|
||||
has a FIFO buffer that can hold messages of a fixed size (32 bytes in this
|
||||
case).
|
||||
|
||||
The mailbox controller also supports interrupt generation, allowing
|
||||
processors to notify each other when a message is available or when an event
|
||||
occurs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: aspeed,ast2700-mailbox
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: TX control register
|
||||
- description: RX control register
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
"#mbox-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- interrupts
|
||||
- "#mbox-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
mailbox@12c1c200 {
|
||||
compatible = "aspeed,ast2700-mailbox";
|
||||
reg = <0x12c1c200 0x100>, <0x12c1c300 0x100>;
|
||||
reg-names = "tx", "rx";
|
||||
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#mbox-cells = <1>;
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mailbox/brcm,bcm74110-mbox.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom BCM74110 Mailbox
|
||||
|
||||
maintainers:
|
||||
- Justin Chen <justin.chen@broadcom.com>
|
||||
- Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
|
||||
description: Broadcom mailbox hardware first introduced with 74110
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm74110-mbox
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: RX doorbell and watermark interrupts
|
||||
- description: TX doorbell and watermark interrupts
|
||||
|
||||
"#mbox-cells":
|
||||
const: 2
|
||||
description:
|
||||
The first cell is channel type and second cell is shared memory slot
|
||||
|
||||
brcm,rx:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: RX Mailbox number
|
||||
|
||||
brcm,tx:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: TX Mailbox number
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- "#mbox-cells"
|
||||
- brcm,rx
|
||||
- brcm,tx
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
mailbox@a552000 {
|
||||
compatible = "brcm,bcm74110-mbox";
|
||||
reg = <0xa552000 0x1104>;
|
||||
interrupts = <GIC_SPI 0x67 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 0x66 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#mbox-cells = <0x2>;
|
||||
brcm,rx = <0x7>;
|
||||
brcm,tx = <0x6>;
|
||||
};
|
||||
@@ -59,9 +59,6 @@ description: |
|
||||
<dt-bindings/mailbox/tegra186-hsp.h>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^hsp@[0-9a-f]+$"
|
||||
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
@@ -131,14 +128,10 @@ examples:
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/mailbox/tegra186-hsp.h>
|
||||
|
||||
hsp_top0: hsp@3c00000 {
|
||||
mailbox@3c00000 {
|
||||
compatible = "nvidia,tegra186-hsp";
|
||||
reg = <0x03c00000 0xa0000>;
|
||||
interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "doorbell";
|
||||
#mbox-cells = <2>;
|
||||
};
|
||||
|
||||
client {
|
||||
mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB TEGRA_HSP_DB_MASTER_CCPLEX>;
|
||||
};
|
||||
|
||||
@@ -251,7 +251,7 @@ examples:
|
||||
# Example apcs with msm8996
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
apcs_glb: mailbox@9820000 {
|
||||
mailbox@9820000 {
|
||||
compatible = "qcom,msm8996-apcs-hmss-global";
|
||||
reg = <0x9820000 0x1000>;
|
||||
|
||||
@@ -259,13 +259,6 @@ examples:
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
rpm-glink {
|
||||
compatible = "qcom,glink-rpm";
|
||||
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
|
||||
qcom,rpm-msg-ram = <&rpm_msg_ram>;
|
||||
mboxes = <&apcs_glb 0>;
|
||||
};
|
||||
|
||||
# Example apcs with qcs404
|
||||
- |
|
||||
#define GCC_APSS_AHB_CLK_SRC 1
|
||||
|
||||
@@ -24,6 +24,7 @@ properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,milos-ipcc
|
||||
- qcom,qcs8300-ipcc
|
||||
- qcom,qdu1000-ipcc
|
||||
- qcom,sa8255p-ipcc
|
||||
|
||||
@@ -242,7 +242,7 @@ examples:
|
||||
- |
|
||||
/* OMAP4 */
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
mailbox: mailbox@4a0f4000 {
|
||||
mailbox@4a0f4000 {
|
||||
compatible = "ti,omap4-mailbox";
|
||||
reg = <0x4a0f4000 0x200>;
|
||||
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
@@ -260,13 +260,9 @@ examples:
|
||||
};
|
||||
};
|
||||
|
||||
dsp {
|
||||
mboxes = <&mailbox &mbox_dsp>;
|
||||
};
|
||||
|
||||
- |
|
||||
/* AM33xx */
|
||||
mailbox1: mailbox@480c8000 {
|
||||
mailbox@480c8000 {
|
||||
compatible = "ti,omap4-mailbox";
|
||||
reg = <0x480c8000 0x200>;
|
||||
interrupts = <77>;
|
||||
@@ -283,7 +279,7 @@ examples:
|
||||
|
||||
- |
|
||||
/* AM65x */
|
||||
mailbox0_cluster0: mailbox@31f80000 {
|
||||
mailbox@31f80000 {
|
||||
compatible = "ti,am654-mailbox";
|
||||
reg = <0x31f80000 0x200>;
|
||||
#mbox-cells = <1>;
|
||||
|
||||
@@ -36,7 +36,7 @@ properties:
|
||||
- const: scfg
|
||||
|
||||
reg:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
@@ -68,12 +68,12 @@ examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
secure_proxy: mailbox@32c00000 {
|
||||
compatible = "ti,am654-secure-proxy";
|
||||
#mbox-cells = <1>;
|
||||
reg-names = "target_data", "rt", "scfg";
|
||||
reg = <0x32c00000 0x100000>,
|
||||
<0x32400000 0x100000>,
|
||||
<0x32800000 0x100000>;
|
||||
interrupt-names = "rx_011";
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
|
||||
compatible = "ti,am654-secure-proxy";
|
||||
#mbox-cells = <1>;
|
||||
reg-names = "target_data", "rt", "scfg";
|
||||
reg = <0x32c00000 0x100000>,
|
||||
<0x32400000 0x100000>,
|
||||
<0x32800000 0x100000>;
|
||||
interrupt-names = "rx_011";
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
@@ -62,11 +62,13 @@ properties:
|
||||
items:
|
||||
- description: GMAC main clock
|
||||
- description: Peripheral registers interface clock
|
||||
- description: APB glue registers interface clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: stmmaceth
|
||||
- const: pclk
|
||||
- const: apb
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
@@ -88,8 +90,8 @@ examples:
|
||||
compatible = "thead,th1520-gmac", "snps,dwmac-3.70a";
|
||||
reg = <0xe7070000 0x2000>, <0xec003000 0x1000>;
|
||||
reg-names = "dwmac", "apb";
|
||||
clocks = <&clk 1>, <&clk 2>;
|
||||
clock-names = "stmmaceth", "pclk";
|
||||
clocks = <&clk 1>, <&clk 2>, <&clk 3>;
|
||||
clock-names = "stmmaceth", "pclk", "apb";
|
||||
interrupts = <66>;
|
||||
interrupt-names = "macirq";
|
||||
phy-mode = "rgmii-id";
|
||||
|
||||
@@ -1420,7 +1420,7 @@ udp_hash_entries - INTEGER
|
||||
A negative value means the networking namespace does not own its
|
||||
hash buckets and shares the initial networking namespace's one.
|
||||
|
||||
udp_child_ehash_entries - INTEGER
|
||||
udp_child_hash_entries - INTEGER
|
||||
Control the number of hash buckets for UDP sockets in the child
|
||||
networking namespace, which must be set before clone() or unshare().
|
||||
|
||||
|
||||
18
MAINTAINERS
18
MAINTAINERS
@@ -11438,6 +11438,7 @@ F: drivers/tty/hvc/
|
||||
HUNG TASK DETECTOR
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
R: Lance Yang <lance.yang@linux.dev>
|
||||
R: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: include/linux/hung_task.h
|
||||
@@ -12583,10 +12584,9 @@ S: Supported
|
||||
F: drivers/cpufreq/intel_pstate.c
|
||||
|
||||
INTEL PTP DFL ToD DRIVER
|
||||
M: Tianfei Zhang <tianfei.zhang@intel.com>
|
||||
L: linux-fpga@vger.kernel.org
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: drivers/ptp/ptp_dfl_tod.c
|
||||
|
||||
INTEL QUADRATURE ENCODER PERIPHERAL DRIVER
|
||||
@@ -12724,9 +12724,8 @@ S: Maintained
|
||||
F: drivers/platform/x86/intel/wmi/thunderbolt.c
|
||||
|
||||
INTEL WWAN IOSM DRIVER
|
||||
M: M Chetan Kumar <m.chetan.kumar@intel.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: drivers/net/wwan/iosm/
|
||||
|
||||
INTEL(R) FLEXIBLE RETURN AND EVENT DELIVERY
|
||||
@@ -13686,7 +13685,6 @@ F: scripts/Makefile.kmsan
|
||||
|
||||
KPROBES
|
||||
M: Naveen N Rao <naveen@kernel.org>
|
||||
M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
|
||||
M: "David S. Miller" <davem@davemloft.net>
|
||||
M: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
@@ -15674,7 +15672,6 @@ MEDIATEK T7XX 5G WWAN MODEM DRIVER
|
||||
M: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
|
||||
R: Chiranjeevi Rapolu <chiranjeevi.rapolu@linux.intel.com>
|
||||
R: Liu Haijun <haijun.liu@mediatek.com>
|
||||
R: M Chetan Kumar <m.chetan.kumar@linux.intel.com>
|
||||
R: Ricardo Martinez <ricardo.martinez@linux.intel.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
@@ -17451,6 +17448,7 @@ F: drivers/net/ethernet/neterion/
|
||||
NETFILTER
|
||||
M: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
M: Jozsef Kadlecsik <kadlec@netfilter.org>
|
||||
M: Florian Westphal <fw@strlen.de>
|
||||
L: netfilter-devel@vger.kernel.org
|
||||
L: coreteam@netfilter.org
|
||||
S: Maintained
|
||||
@@ -21487,6 +21485,14 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/renesas,rzv2h-gbeth.yaml
|
||||
F: drivers/net/ethernet/stmicro/stmmac/dwmac-renesas-gbeth.c
|
||||
|
||||
RENESAS RZ/V2H(P) RSPI DRIVER
|
||||
M: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
|
||||
L: linux-spi@vger.kernel.org
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml
|
||||
F: drivers/spi/spi-rzv2h-rspi.c
|
||||
|
||||
RENESAS RZ/V2H(P) USB2PHY PORT RESET DRIVER
|
||||
M: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
|
||||
M: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
|
||||
|
||||
4
Makefile
4
Makefile
@@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 16
|
||||
PATCHLEVEL = 17
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION =
|
||||
EXTRAVERSION = -rc1
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
@@ -237,7 +237,8 @@ memc@0 {
|
||||
ranges = <0x0 0x0 0x80000>;
|
||||
|
||||
memc-ddr@2000 {
|
||||
compatible = "brcm,brcmstb-memc-ddr";
|
||||
compatible = "brcm,brcmstb-memc-ddr-rev-b.1.x",
|
||||
"brcm,brcmstb-memc-ddr";
|
||||
reg = <0x2000 0x800>;
|
||||
};
|
||||
|
||||
@@ -259,7 +260,8 @@ memc@80000 {
|
||||
ranges = <0x0 0x80000 0x80000>;
|
||||
|
||||
memc-ddr@2000 {
|
||||
compatible = "brcm,brcmstb-memc-ddr";
|
||||
compatible = "brcm,brcmstb-memc-ddr-rev-b.1.x",
|
||||
"brcm,brcmstb-memc-ddr";
|
||||
reg = <0x2000 0x800>;
|
||||
};
|
||||
|
||||
@@ -281,7 +283,8 @@ memc@100000 {
|
||||
ranges = <0x0 0x100000 0x80000>;
|
||||
|
||||
memc-ddr@2000 {
|
||||
compatible = "brcm,brcmstb-memc-ddr";
|
||||
compatible = "brcm,brcmstb-memc-ddr-rev-b.1.x",
|
||||
"brcm,brcmstb-memc-ddr";
|
||||
reg = <0x2000 0x800>;
|
||||
};
|
||||
|
||||
|
||||
@@ -617,8 +617,8 @@ static int sa1111_setup_gpios(struct sa1111 *sachip)
|
||||
sachip->gc.direction_input = sa1111_gpio_direction_input;
|
||||
sachip->gc.direction_output = sa1111_gpio_direction_output;
|
||||
sachip->gc.get = sa1111_gpio_get;
|
||||
sachip->gc.set_rv = sa1111_gpio_set;
|
||||
sachip->gc.set_multiple_rv = sa1111_gpio_set_multiple;
|
||||
sachip->gc.set = sa1111_gpio_set;
|
||||
sachip->gc.set_multiple = sa1111_gpio_set_multiple;
|
||||
sachip->gc.to_irq = sa1111_gpio_to_irq;
|
||||
sachip->gc.base = -1;
|
||||
sachip->gc.ngpio = 18;
|
||||
|
||||
@@ -218,7 +218,7 @@ static int scoop_probe(struct platform_device *pdev)
|
||||
devptr->gpio.label = dev_name(&pdev->dev);
|
||||
devptr->gpio.base = inf->gpio_base;
|
||||
devptr->gpio.ngpio = 12; /* PA11 = 0, PA12 = 1, etc. up to PA22 = 11 */
|
||||
devptr->gpio.set_rv = scoop_gpio_set;
|
||||
devptr->gpio.set = scoop_gpio_set;
|
||||
devptr->gpio.get = scoop_gpio_get;
|
||||
devptr->gpio.direction_input = scoop_gpio_direction_input;
|
||||
devptr->gpio.direction_output = scoop_gpio_direction_output;
|
||||
|
||||
@@ -517,7 +517,7 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
|
||||
if (!gc->direction_output)
|
||||
gc->direction_output = samsung_gpiolib_2bit_output;
|
||||
if (!gc->set)
|
||||
gc->set_rv = samsung_gpiolib_set;
|
||||
gc->set = samsung_gpiolib_set;
|
||||
if (!gc->get)
|
||||
gc->get = samsung_gpiolib_get;
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ void ASSABET_BCR_frob(unsigned int mask, unsigned int val)
|
||||
{
|
||||
unsigned long m = mask, v = val;
|
||||
|
||||
assabet_bcr_gc->set_multiple_rv(assabet_bcr_gc, &m, &v);
|
||||
assabet_bcr_gc->set_multiple(assabet_bcr_gc, &m, &v);
|
||||
}
|
||||
EXPORT_SYMBOL(ASSABET_BCR_frob);
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ void neponset_ncr_frob(unsigned int mask, unsigned int val)
|
||||
unsigned long m = mask, v = val;
|
||||
|
||||
if (nep)
|
||||
n->gpio[0]->set_multiple_rv(n->gpio[0], &m, &v);
|
||||
n->gpio[0]->set_multiple(n->gpio[0], &m, &v);
|
||||
else
|
||||
WARN(1, "nep unset\n");
|
||||
}
|
||||
|
||||
@@ -540,7 +540,7 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
|
||||
ochip->chip.direction_input = orion_gpio_direction_input;
|
||||
ochip->chip.get = orion_gpio_get;
|
||||
ochip->chip.direction_output = orion_gpio_direction_output;
|
||||
ochip->chip.set_rv = orion_gpio_set;
|
||||
ochip->chip.set = orion_gpio_set;
|
||||
ochip->chip.to_irq = orion_gpio_to_irq;
|
||||
ochip->chip.base = gpio_base;
|
||||
ochip->chip.ngpio = ngpio;
|
||||
|
||||
@@ -11,7 +11,6 @@ / {
|
||||
interrupt-parent = <&gic>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
numa-node-id = <0>;
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
@@ -341,7 +340,6 @@ cpu0: cpu@0 {
|
||||
status = "okay";
|
||||
|
||||
enable-method = "psci";
|
||||
numa-node-id = <0>;
|
||||
|
||||
i-cache-size = <65536>;
|
||||
i-cache-line-size = <64>;
|
||||
@@ -358,7 +356,6 @@ cpu1: cpu@1 {
|
||||
status = "okay";
|
||||
|
||||
enable-method = "psci";
|
||||
numa-node-id = <0>;
|
||||
|
||||
i-cache-size = <65536>;
|
||||
i-cache-line-size = <64>;
|
||||
|
||||
@@ -160,7 +160,7 @@ static struct gpio_chip mcfgpio_chip = {
|
||||
.direction_input = mcfgpio_direction_input,
|
||||
.direction_output = mcfgpio_direction_output,
|
||||
.get = mcfgpio_get_value,
|
||||
.set_rv = mcfgpio_set_value,
|
||||
.set = mcfgpio_set_value,
|
||||
.to_irq = mcfgpio_to_irq,
|
||||
.base = 0,
|
||||
.ngpio = MCFGPIO_PIN_MAX,
|
||||
|
||||
@@ -101,7 +101,7 @@ struct gpio_chip alchemy_gpio_chip[] = {
|
||||
.direction_input = gpio1_direction_input,
|
||||
.direction_output = gpio1_direction_output,
|
||||
.get = gpio1_get,
|
||||
.set_rv = gpio1_set,
|
||||
.set = gpio1_set,
|
||||
.to_irq = gpio1_to_irq,
|
||||
.base = ALCHEMY_GPIO1_BASE,
|
||||
.ngpio = ALCHEMY_GPIO1_NUM,
|
||||
@@ -111,7 +111,7 @@ struct gpio_chip alchemy_gpio_chip[] = {
|
||||
.direction_input = gpio2_direction_input,
|
||||
.direction_output = gpio2_direction_output,
|
||||
.get = gpio2_get,
|
||||
.set_rv = gpio2_set,
|
||||
.set = gpio2_set,
|
||||
.to_irq = gpio2_to_irq,
|
||||
.base = ALCHEMY_GPIO2_BASE,
|
||||
.ngpio = ALCHEMY_GPIO2_NUM,
|
||||
@@ -151,7 +151,7 @@ static struct gpio_chip au1300_gpiochip = {
|
||||
.direction_input = alchemy_gpic_dir_input,
|
||||
.direction_output = alchemy_gpic_dir_output,
|
||||
.get = alchemy_gpic_get,
|
||||
.set_rv = alchemy_gpic_set,
|
||||
.set = alchemy_gpic_set,
|
||||
.to_irq = alchemy_gpic_gpio_to_irq,
|
||||
.base = AU1300_GPIO_BASE,
|
||||
.ngpio = AU1300_GPIO_NUM,
|
||||
|
||||
@@ -131,7 +131,7 @@ static struct gpio_chip bcm63xx_gpio_chip = {
|
||||
.direction_input = bcm63xx_gpio_direction_input,
|
||||
.direction_output = bcm63xx_gpio_direction_output,
|
||||
.get = bcm63xx_gpio_get,
|
||||
.set_rv = bcm63xx_gpio_set,
|
||||
.set = bcm63xx_gpio_set,
|
||||
.base = 0,
|
||||
};
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ static int txx9_gpio_dir_out(struct gpio_chip *chip, unsigned int offset,
|
||||
|
||||
static struct gpio_chip txx9_gpio_chip = {
|
||||
.get = txx9_gpio_get,
|
||||
.set_rv = txx9_gpio_set,
|
||||
.set = txx9_gpio_set,
|
||||
.direction_input = txx9_gpio_dir_in,
|
||||
.direction_output = txx9_gpio_dir_out,
|
||||
.label = "TXx9",
|
||||
|
||||
@@ -164,7 +164,7 @@ static struct rb532_gpio_chip rb532_gpio_chip[] = {
|
||||
.direction_input = rb532_gpio_direction_input,
|
||||
.direction_output = rb532_gpio_direction_output,
|
||||
.get = rb532_gpio_get,
|
||||
.set_rv = rb532_gpio_set,
|
||||
.set = rb532_gpio_set,
|
||||
.to_irq = rb532_gpio_to_irq,
|
||||
.base = 0,
|
||||
.ngpio = 32,
|
||||
|
||||
@@ -655,7 +655,7 @@ void __init txx9_iocled_init(unsigned long baseaddr,
|
||||
if (!iocled->mmioaddr)
|
||||
goto out_free;
|
||||
iocled->chip.get = txx9_iocled_get;
|
||||
iocled->chip.set_rv = txx9_iocled_set;
|
||||
iocled->chip.set = txx9_iocled_set;
|
||||
iocled->chip.direction_input = txx9_iocled_dir_in;
|
||||
iocled->chip.direction_output = txx9_iocled_dir_out;
|
||||
iocled->chip.label = "iocled";
|
||||
|
||||
@@ -180,7 +180,7 @@ static int __init ppc4xx_add_gpiochips(void)
|
||||
gc->direction_input = ppc4xx_gpio_dir_in;
|
||||
gc->direction_output = ppc4xx_gpio_dir_out;
|
||||
gc->get = ppc4xx_gpio_get;
|
||||
gc->set_rv = ppc4xx_gpio_set;
|
||||
gc->set = ppc4xx_gpio_set;
|
||||
|
||||
ret = of_mm_gpiochip_add_data(np, mm_gc, ppc4xx_gc);
|
||||
if (ret)
|
||||
|
||||
@@ -336,7 +336,7 @@ static void mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt)
|
||||
gpt->gc.direction_input = mpc52xx_gpt_gpio_dir_in;
|
||||
gpt->gc.direction_output = mpc52xx_gpt_gpio_dir_out;
|
||||
gpt->gc.get = mpc52xx_gpt_gpio_get;
|
||||
gpt->gc.set_rv = mpc52xx_gpt_gpio_set;
|
||||
gpt->gc.set = mpc52xx_gpt_gpio_set;
|
||||
gpt->gc.base = -1;
|
||||
gpt->gc.parent = gpt->dev;
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ static int mcu_gpiochip_add(struct mcu *mcu)
|
||||
gc->can_sleep = 1;
|
||||
gc->ngpio = MCU_NUM_GPIO;
|
||||
gc->base = -1;
|
||||
gc->set_rv = mcu_gpio_set;
|
||||
gc->set = mcu_gpio_set;
|
||||
gc->direction_output = mcu_gpio_dir_out;
|
||||
gc->parent = dev;
|
||||
|
||||
|
||||
@@ -499,7 +499,7 @@ int cpm1_gpiochip_add16(struct device *dev)
|
||||
gc->direction_input = cpm1_gpio16_dir_in;
|
||||
gc->direction_output = cpm1_gpio16_dir_out;
|
||||
gc->get = cpm1_gpio16_get;
|
||||
gc->set_rv = cpm1_gpio16_set;
|
||||
gc->set = cpm1_gpio16_set;
|
||||
gc->to_irq = cpm1_gpio16_to_irq;
|
||||
gc->parent = dev;
|
||||
gc->owner = THIS_MODULE;
|
||||
@@ -622,7 +622,7 @@ int cpm1_gpiochip_add32(struct device *dev)
|
||||
gc->direction_input = cpm1_gpio32_dir_in;
|
||||
gc->direction_output = cpm1_gpio32_dir_out;
|
||||
gc->get = cpm1_gpio32_get;
|
||||
gc->set_rv = cpm1_gpio32_set;
|
||||
gc->set = cpm1_gpio32_set;
|
||||
gc->parent = dev;
|
||||
gc->owner = THIS_MODULE;
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ int cpm2_gpiochip_add32(struct device *dev)
|
||||
gc->direction_input = cpm2_gpio32_dir_in;
|
||||
gc->direction_output = cpm2_gpio32_dir_out;
|
||||
gc->get = cpm2_gpio32_get;
|
||||
gc->set_rv = cpm2_gpio32_set;
|
||||
gc->set = cpm2_gpio32_set;
|
||||
gc->parent = dev;
|
||||
gc->owner = THIS_MODULE;
|
||||
|
||||
|
||||
@@ -297,8 +297,9 @@ gmac1: ethernet@ffe7060000 {
|
||||
reg-names = "dwmac", "apb";
|
||||
interrupts = <67 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "macirq";
|
||||
clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC1>;
|
||||
clock-names = "stmmaceth", "pclk";
|
||||
clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC1>,
|
||||
<&clk CLK_PERISYS_APB4_HCLK>;
|
||||
clock-names = "stmmaceth", "pclk", "apb";
|
||||
snps,pbl = <32>;
|
||||
snps,fixed-burst;
|
||||
snps,multicast-filter-bins = <64>;
|
||||
@@ -319,8 +320,9 @@ gmac0: ethernet@ffe7070000 {
|
||||
reg-names = "dwmac", "apb";
|
||||
interrupts = <66 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "macirq";
|
||||
clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC0>;
|
||||
clock-names = "stmmaceth", "pclk";
|
||||
clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC0>,
|
||||
<&clk CLK_PERISYS_APB4_HCLK>;
|
||||
clock-names = "stmmaceth", "pclk", "apb";
|
||||
snps,pbl = <32>;
|
||||
snps,fixed-burst;
|
||||
snps,multicast-filter-bins = <64>;
|
||||
|
||||
@@ -106,5 +106,18 @@ void get_cpuflags(void)
|
||||
cpuid(0x80000001, &ignored, &ignored, &cpu.flags[6],
|
||||
&cpu.flags[1]);
|
||||
}
|
||||
|
||||
if (max_amd_level >= 0x8000001f) {
|
||||
u32 ebx;
|
||||
|
||||
/*
|
||||
* The X86_FEATURE_COHERENCY_SFW_NO feature bit is in
|
||||
* the virtualization flags entry (word 8) and set by
|
||||
* scattered.c, so the bit needs to be explicitly set.
|
||||
*/
|
||||
cpuid(0x8000001f, &ignored, &ebx, &ignored, &ignored);
|
||||
if (ebx & BIT(31))
|
||||
set_bit(X86_FEATURE_COHERENCY_SFW_NO, cpu.flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,6 +810,13 @@ static void __head pvalidate_4k_page(unsigned long vaddr, unsigned long paddr,
|
||||
if (ret)
|
||||
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If validating memory (making it private) and affected by the
|
||||
* cache-coherency vulnerability, perform the cache eviction mitigation.
|
||||
*/
|
||||
if (validate && !has_cpuflag(X86_FEATURE_COHERENCY_SFW_NO))
|
||||
sev_evict_cache((void *)vaddr, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -358,10 +358,31 @@ static void svsm_pval_pages(struct snp_psc_desc *desc)
|
||||
|
||||
static void pvalidate_pages(struct snp_psc_desc *desc)
|
||||
{
|
||||
struct psc_entry *e;
|
||||
unsigned int i;
|
||||
|
||||
if (snp_vmpl)
|
||||
svsm_pval_pages(desc);
|
||||
else
|
||||
pval_pages(desc);
|
||||
|
||||
/*
|
||||
* If not affected by the cache-coherency vulnerability there is no need
|
||||
* to perform the cache eviction mitigation.
|
||||
*/
|
||||
if (cpu_feature_enabled(X86_FEATURE_COHERENCY_SFW_NO))
|
||||
return;
|
||||
|
||||
for (i = 0; i <= desc->hdr.end_entry; i++) {
|
||||
e = &desc->entries[i];
|
||||
|
||||
/*
|
||||
* If validating memory (making it private) perform the cache
|
||||
* eviction mitigation.
|
||||
*/
|
||||
if (e->operation == SNP_PAGE_STATE_PRIVATE)
|
||||
sev_evict_cache(pfn_to_kaddr(e->gfn), e->pagesize ? 512 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int vmgexit_psc(struct ghcb *ghcb, struct snp_psc_desc *desc)
|
||||
|
||||
@@ -218,6 +218,7 @@
|
||||
#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 1) /* "flexpriority" Intel FlexPriority */
|
||||
#define X86_FEATURE_EPT ( 8*32+ 2) /* "ept" Intel Extended Page Table */
|
||||
#define X86_FEATURE_VPID ( 8*32+ 3) /* "vpid" Intel Virtual Processor ID */
|
||||
#define X86_FEATURE_COHERENCY_SFW_NO ( 8*32+ 4) /* SNP cache coherency software work around not needed */
|
||||
|
||||
#define X86_FEATURE_VMMCALL ( 8*32+15) /* "vmmcall" Prefer VMMCALL to VMCALL */
|
||||
#define X86_FEATURE_XENPV ( 8*32+16) /* Xen paravirtual guest */
|
||||
|
||||
@@ -92,8 +92,6 @@ struct irq_cfg {
|
||||
|
||||
extern struct irq_cfg *irq_cfg(unsigned int irq);
|
||||
extern struct irq_cfg *irqd_cfg(struct irq_data *irq_data);
|
||||
extern void lock_vector_lock(void);
|
||||
extern void unlock_vector_lock(void);
|
||||
#ifdef CONFIG_SMP
|
||||
extern void vector_schedule_cleanup(struct irq_cfg *);
|
||||
extern void irq_complete_move(struct irq_cfg *cfg);
|
||||
@@ -101,12 +99,16 @@ extern void irq_complete_move(struct irq_cfg *cfg);
|
||||
static inline void vector_schedule_cleanup(struct irq_cfg *c) { }
|
||||
static inline void irq_complete_move(struct irq_cfg *c) { }
|
||||
#endif
|
||||
|
||||
extern void apic_ack_edge(struct irq_data *data);
|
||||
#else /* CONFIG_IRQ_DOMAIN_HIERARCHY */
|
||||
#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
extern void lock_vector_lock(void);
|
||||
extern void unlock_vector_lock(void);
|
||||
#else
|
||||
static inline void lock_vector_lock(void) {}
|
||||
static inline void unlock_vector_lock(void) {}
|
||||
#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
|
||||
#endif
|
||||
|
||||
/* Statistics */
|
||||
extern atomic_t irq_err_count;
|
||||
|
||||
@@ -150,6 +150,11 @@
|
||||
|
||||
#define INTEL_PANTHERLAKE_L IFM(6, 0xCC) /* Cougar Cove / Crestmont */
|
||||
|
||||
#define INTEL_WILDCATLAKE_L IFM(6, 0xD5)
|
||||
|
||||
#define INTEL_NOVALAKE IFM(18, 0x01)
|
||||
#define INTEL_NOVALAKE_L IFM(18, 0x03)
|
||||
|
||||
/* "Small Core" Processors (Atom/E-Core) */
|
||||
|
||||
#define INTEL_ATOM_BONNELL IFM(6, 0x1C) /* Diamondville, Pineview */
|
||||
|
||||
@@ -619,6 +619,24 @@ int rmp_make_shared(u64 pfn, enum pg_level level);
|
||||
void snp_leak_pages(u64 pfn, unsigned int npages);
|
||||
void kdump_sev_callback(void);
|
||||
void snp_fixup_e820_tables(void);
|
||||
|
||||
static inline void sev_evict_cache(void *va, int npages)
|
||||
{
|
||||
volatile u8 val __always_unused;
|
||||
u8 *bytes = va;
|
||||
int page_idx;
|
||||
|
||||
/*
|
||||
* For SEV guests, a read from the first/last cache-lines of a 4K page
|
||||
* using the guest key is sufficient to cause a flush of all cache-lines
|
||||
* associated with that 4K page without incurring all the overhead of a
|
||||
* full CLFLUSH sequence.
|
||||
*/
|
||||
for (page_idx = 0; page_idx < npages; page_idx++) {
|
||||
val = bytes[page_idx * PAGE_SIZE];
|
||||
val = bytes[page_idx * PAGE_SIZE + PAGE_SIZE - 1];
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline bool snp_probe_rmptable_info(void) { return false; }
|
||||
static inline int snp_rmptable_init(void) { return -ENOSYS; }
|
||||
@@ -634,6 +652,7 @@ static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV
|
||||
static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
|
||||
static inline void kdump_sev_callback(void) { }
|
||||
static inline void snp_fixup_e820_tables(void) {}
|
||||
static inline void sev_evict_cache(void *va, int npages) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,6 +48,7 @@ static const struct cpuid_bit cpuid_bits[] = {
|
||||
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },
|
||||
{ X86_FEATURE_AMD_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 },
|
||||
{ X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 },
|
||||
{ X86_FEATURE_COHERENCY_SFW_NO, CPUID_EBX, 31, 0x8000001f, 0 },
|
||||
{ X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 },
|
||||
{ X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 },
|
||||
{ X86_FEATURE_TSA_SQ_NO, CPUID_ECX, 1, 0x80000021, 0 },
|
||||
|
||||
@@ -256,26 +256,59 @@ static __always_inline void handle_irq(struct irq_desc *desc,
|
||||
__handle_irq(desc, regs);
|
||||
}
|
||||
|
||||
static __always_inline int call_irq_handler(int vector, struct pt_regs *regs)
|
||||
static struct irq_desc *reevaluate_vector(int vector)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
int ret = 0;
|
||||
struct irq_desc *desc = __this_cpu_read(vector_irq[vector]);
|
||||
|
||||
if (!IS_ERR_OR_NULL(desc))
|
||||
return desc;
|
||||
|
||||
if (desc == VECTOR_UNUSED)
|
||||
pr_emerg_ratelimited("No irq handler for %d.%u\n", smp_processor_id(), vector);
|
||||
else
|
||||
__this_cpu_write(vector_irq[vector], VECTOR_UNUSED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __always_inline bool call_irq_handler(int vector, struct pt_regs *regs)
|
||||
{
|
||||
struct irq_desc *desc = __this_cpu_read(vector_irq[vector]);
|
||||
|
||||
desc = __this_cpu_read(vector_irq[vector]);
|
||||
if (likely(!IS_ERR_OR_NULL(desc))) {
|
||||
handle_irq(desc, regs);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
if (desc == VECTOR_UNUSED) {
|
||||
pr_emerg_ratelimited("%s: %d.%u No irq handler for vector\n",
|
||||
__func__, smp_processor_id(),
|
||||
vector);
|
||||
} else {
|
||||
__this_cpu_write(vector_irq[vector], VECTOR_UNUSED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
/*
|
||||
* Reevaluate with vector_lock held to prevent a race against
|
||||
* request_irq() setting up the vector:
|
||||
*
|
||||
* CPU0 CPU1
|
||||
* interrupt is raised in APIC IRR
|
||||
* but not handled
|
||||
* free_irq()
|
||||
* per_cpu(vector_irq, CPU1)[vector] = VECTOR_SHUTDOWN;
|
||||
*
|
||||
* request_irq() common_interrupt()
|
||||
* d = this_cpu_read(vector_irq[vector]);
|
||||
*
|
||||
* per_cpu(vector_irq, CPU1)[vector] = desc;
|
||||
*
|
||||
* if (d == VECTOR_SHUTDOWN)
|
||||
* this_cpu_write(vector_irq[vector], VECTOR_UNUSED);
|
||||
*
|
||||
* This requires that the same vector on the same target CPU is
|
||||
* handed out or that a spurious interrupt hits that CPU/vector.
|
||||
*/
|
||||
lock_vector_lock();
|
||||
desc = reevaluate_vector(vector);
|
||||
unlock_vector_lock();
|
||||
|
||||
if (!desc)
|
||||
return false;
|
||||
|
||||
handle_irq(desc, regs);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -289,7 +322,7 @@ DEFINE_IDTENTRY_IRQ(common_interrupt)
|
||||
/* entry code tells RCU that we're not quiescent. Check it. */
|
||||
RCU_LOCKDEP_WARN(!rcu_is_watching(), "IRQ failed to wake up RCU");
|
||||
|
||||
if (unlikely(call_irq_handler(vector, regs)))
|
||||
if (unlikely(!call_irq_handler(vector, regs)))
|
||||
apic_eoi();
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define BP_TAG_FIRST 0x7B0B /* first tag with a version number */
|
||||
#define BP_TAG_LAST 0x7E0B /* last tag */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
/* All records are aligned to 4 bytes */
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef _XTENSA_CMPXCHG_H
|
||||
#define _XTENSA_CMPXCHG_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/stringify.h>
|
||||
@@ -220,6 +220,6 @@ __arch_xchg(unsigned long x, volatile void * ptr, int size)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* _XTENSA_CMPXCHG_H */
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <asm/core.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#ifdef __ASSEMBLER__
|
||||
# include <variant/tie-asm.h>
|
||||
|
||||
.macro xchal_sa_start a b
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
/*
|
||||
* XTENSA_HAVE_COPROCESSOR(x) returns 1 if coprocessor x is configured.
|
||||
@@ -87,7 +87,7 @@
|
||||
#define XTENSA_HAVE_IO_PORTS \
|
||||
XCHAL_CP_PORT_MASK
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
/*
|
||||
* Additional registers.
|
||||
@@ -151,5 +151,5 @@ void local_coprocessors_flush_release_all(void);
|
||||
|
||||
#endif /* XTENSA_HAVE_COPROCESSORS */
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
#endif /* _XTENSA_COPROCESSOR_H */
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <linux/thread_info.h>
|
||||
|
||||
|
||||
@@ -12,20 +12,20 @@
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
extern unsigned long return_address(unsigned level);
|
||||
#define ftrace_return_address(n) return_address(n)
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
|
||||
#define MCOUNT_ADDR ((unsigned long)(_mcount))
|
||||
#define MCOUNT_INSN_SIZE 3
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
extern void _mcount(void);
|
||||
#define mcount _mcount
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* CONFIG_FUNCTION_TRACER */
|
||||
|
||||
#endif /* _XTENSA_FTRACE_H */
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#define CA_WRITEBACK (0x4)
|
||||
#endif
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#ifdef __ASSEMBLER__
|
||||
|
||||
#define XTENSA_HWVERSION_RC_2009_0 230000
|
||||
|
||||
@@ -240,6 +240,6 @@
|
||||
|
||||
.endm
|
||||
|
||||
#endif /*__ASSEMBLY__*/
|
||||
#endif /*__ASSEMBLER__*/
|
||||
|
||||
#endif /* _XTENSA_INITIALIZE_MMU_H */
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#ifndef _ASM_XTENSA_JUMP_LABEL_H
|
||||
#define _ASM_XTENSA_JUMP_LABEL_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
@@ -61,5 +61,5 @@ struct jump_entry {
|
||||
jump_label_t key;
|
||||
};
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#ifndef __ASM_KASAN_H
|
||||
#define __ASM_KASAN_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#ifdef CONFIG_KASAN
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
#if (!XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY) && defined(CONFIG_USE_OF)
|
||||
#define XCHAL_KIO_PADDR xtensa_get_kio_paddr()
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
extern unsigned long xtensa_kio_paddr;
|
||||
|
||||
static inline unsigned long xtensa_get_kio_paddr(void)
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#ifdef __ASSEMBLER__
|
||||
|
||||
#define __pgprot(x) (x)
|
||||
|
||||
@@ -172,7 +172,7 @@ static inline unsigned long ___pa(unsigned long va)
|
||||
#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
|
||||
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#include <asm-generic/memory_model.h>
|
||||
#endif /* _XTENSA_PAGE_H */
|
||||
|
||||
@@ -203,7 +203,7 @@
|
||||
* What follows is the closest we can get by reasonable means..
|
||||
* See linux/mm/mmap.c for protection_map[] array that uses these definitions.
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#define pte_ERROR(e) \
|
||||
printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
|
||||
@@ -366,10 +366,10 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
|
||||
return pte;
|
||||
}
|
||||
|
||||
#endif /* !defined (__ASSEMBLY__) */
|
||||
#endif /* !defined (__ASSEMBLER__) */
|
||||
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#ifdef __ASSEMBLER__
|
||||
|
||||
/* Assembly macro _PGD_INDEX is the same as C pgd_index(unsigned long),
|
||||
* _PGD_OFFSET as C pgd_offset(struct mm_struct*, unsigned long),
|
||||
@@ -408,7 +408,7 @@ void update_mmu_tlb_range(struct vm_area_struct *vma,
|
||||
unsigned long address, pte_t *ptep, unsigned int nr);
|
||||
#define update_mmu_tlb_range update_mmu_tlb_range
|
||||
|
||||
#endif /* !defined (__ASSEMBLY__) */
|
||||
#endif /* !defined (__ASSEMBLER__) */
|
||||
|
||||
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
|
||||
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
#error Unsupported xtensa ABI
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#if defined(__XTENSA_WINDOWED_ABI__)
|
||||
|
||||
@@ -263,5 +263,5 @@ static inline unsigned long get_er(unsigned long addr)
|
||||
|
||||
#endif /* XCHAL_HAVE_EXTERN_REGS */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* _XTENSA_PROCESSOR_H */
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
#define NO_SYSCALL (-1)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <asm/coprocessor.h>
|
||||
#include <asm/core.h>
|
||||
@@ -106,11 +106,11 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
|
||||
int do_syscall_trace_enter(struct pt_regs *regs);
|
||||
void do_syscall_trace_leave(struct pt_regs *regs);
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
#else /* __ASSEMBLER__ */
|
||||
|
||||
# include <asm/asm-offsets.h>
|
||||
#define PT_REGS_OFFSET (KERNEL_STACK_SIZE - PT_USER_SIZE)
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
#endif /* _XTENSA_PTRACE_H */
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
#include <uapi/asm/signal.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
#define __ARCH_HAS_SA_RESTORER
|
||||
|
||||
#include <asm/sigcontext.h>
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* _XTENSA_SIGNAL_H */
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#define CURRENT_SHIFT KERNEL_STACK_SHIFT
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
# include <asm/processor.h>
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
* must also be changed
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#if XTENSA_HAVE_COPROCESSORS
|
||||
|
||||
@@ -80,7 +80,7 @@ struct thread_info {
|
||||
* macros/functions for gaining access to the thread information structure
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
@@ -99,7 +99,7 @@ static __always_inline struct thread_info *current_thread_info(void)
|
||||
return ti;
|
||||
}
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
#else /* !__ASSEMBLER__ */
|
||||
|
||||
/* how to get the thread information struct from ASM */
|
||||
#define GET_THREAD_INFO(reg,sp) \
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define ITLB_HIT_BIT 3
|
||||
#define DTLB_HIT_BIT 4
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
/* TLB flushing:
|
||||
*
|
||||
@@ -201,5 +201,5 @@ static inline unsigned long read_itlb_translation (int way)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* _XTENSA_TLBFLUSH_H */
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#define PTRACE_GETFDPIC_EXEC 0
|
||||
#define PTRACE_GETFDPIC_INTERP 1
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
struct user_pt_regs {
|
||||
__u32 pc;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#define _NSIG_BPW 32
|
||||
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
@@ -77,7 +77,7 @@ typedef struct {
|
||||
#define MINSIGSTKSZ 2048
|
||||
#define SIGSTKSZ 8192
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <asm-generic/signal-defs.h>
|
||||
|
||||
@@ -106,5 +106,5 @@ typedef struct sigaltstack {
|
||||
__kernel_size_t ss_size;
|
||||
} stack_t;
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* _UAPI_XTENSA_SIGNAL_H */
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <asm-generic/int-ll64.h>
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#ifdef __ASSEMBLER__
|
||||
# define __XTENSA_UL(x) (x)
|
||||
# define __XTENSA_UL_CONST(x) x
|
||||
#else
|
||||
@@ -23,7 +23,7 @@
|
||||
# define __XTENSA_UL_CONST(x) ___XTENSA_UL_CONST(x)
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -454,17 +454,10 @@ static struct bfq_io_cq *icq_to_bic(struct io_cq *icq)
|
||||
*/
|
||||
static struct bfq_io_cq *bfq_bic_lookup(struct request_queue *q)
|
||||
{
|
||||
struct bfq_io_cq *icq;
|
||||
unsigned long flags;
|
||||
|
||||
if (!current->io_context)
|
||||
return NULL;
|
||||
|
||||
spin_lock_irqsave(&q->queue_lock, flags);
|
||||
icq = icq_to_bic(ioc_lookup_icq(q));
|
||||
spin_unlock_irqrestore(&q->queue_lock, flags);
|
||||
|
||||
return icq;
|
||||
return icq_to_bic(ioc_lookup_icq(q));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -701,17 +694,13 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
|
||||
{
|
||||
struct bfq_data *bfqd = data->q->elevator->elevator_data;
|
||||
struct bfq_io_cq *bic = bfq_bic_lookup(data->q);
|
||||
int depth;
|
||||
unsigned limit = data->q->nr_requests;
|
||||
unsigned int act_idx;
|
||||
unsigned int limit, act_idx;
|
||||
|
||||
/* Sync reads have full depth available */
|
||||
if (op_is_sync(opf) && !op_is_write(opf)) {
|
||||
depth = 0;
|
||||
} else {
|
||||
depth = bfqd->word_depths[!!bfqd->wr_busy_queues][op_is_sync(opf)];
|
||||
limit = (limit * depth) >> bfqd->full_depth_shift;
|
||||
}
|
||||
if (op_is_sync(opf) && !op_is_write(opf))
|
||||
limit = data->q->nr_requests;
|
||||
else
|
||||
limit = bfqd->async_depths[!!bfqd->wr_busy_queues][op_is_sync(opf)];
|
||||
|
||||
for (act_idx = 0; bic && act_idx < bfqd->num_actuators; act_idx++) {
|
||||
/* Fast path to check if bfqq is already allocated. */
|
||||
@@ -725,14 +714,16 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
|
||||
* available requests and thus starve other entities.
|
||||
*/
|
||||
if (bfqq_request_over_limit(bfqd, bic, opf, act_idx, limit)) {
|
||||
depth = 1;
|
||||
limit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bfq_log(bfqd, "[%s] wr_busy %d sync %d depth %u",
|
||||
__func__, bfqd->wr_busy_queues, op_is_sync(opf), depth);
|
||||
if (depth)
|
||||
data->shallow_depth = depth;
|
||||
__func__, bfqd->wr_busy_queues, op_is_sync(opf), limit);
|
||||
|
||||
if (limit < data->q->nr_requests)
|
||||
data->shallow_depth = limit;
|
||||
}
|
||||
|
||||
static struct bfq_queue *
|
||||
@@ -2457,15 +2448,8 @@ static bool bfq_bio_merge(struct request_queue *q, struct bio *bio,
|
||||
unsigned int nr_segs)
|
||||
{
|
||||
struct bfq_data *bfqd = q->elevator->elevator_data;
|
||||
struct request *free = NULL;
|
||||
/*
|
||||
* bfq_bic_lookup grabs the queue_lock: invoke it now and
|
||||
* store its return value for later use, to avoid nesting
|
||||
* queue_lock inside the bfqd->lock. We assume that the bic
|
||||
* returned by bfq_bic_lookup does not go away before
|
||||
* bfqd->lock is taken.
|
||||
*/
|
||||
struct bfq_io_cq *bic = bfq_bic_lookup(q);
|
||||
struct request *free = NULL;
|
||||
bool ret;
|
||||
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
@@ -7128,9 +7112,8 @@ void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg)
|
||||
*/
|
||||
static void bfq_update_depths(struct bfq_data *bfqd, struct sbitmap_queue *bt)
|
||||
{
|
||||
unsigned int depth = 1U << bt->sb.shift;
|
||||
unsigned int nr_requests = bfqd->queue->nr_requests;
|
||||
|
||||
bfqd->full_depth_shift = bt->sb.shift;
|
||||
/*
|
||||
* In-word depths if no bfq_queue is being weight-raised:
|
||||
* leaving 25% of tags only for sync reads.
|
||||
@@ -7142,13 +7125,13 @@ static void bfq_update_depths(struct bfq_data *bfqd, struct sbitmap_queue *bt)
|
||||
* limit 'something'.
|
||||
*/
|
||||
/* no more than 50% of tags for async I/O */
|
||||
bfqd->word_depths[0][0] = max(depth >> 1, 1U);
|
||||
bfqd->async_depths[0][0] = max(nr_requests >> 1, 1U);
|
||||
/*
|
||||
* no more than 75% of tags for sync writes (25% extra tags
|
||||
* w.r.t. async I/O, to prevent async I/O from starving sync
|
||||
* writes)
|
||||
*/
|
||||
bfqd->word_depths[0][1] = max((depth * 3) >> 2, 1U);
|
||||
bfqd->async_depths[0][1] = max((nr_requests * 3) >> 2, 1U);
|
||||
|
||||
/*
|
||||
* In-word depths in case some bfq_queue is being weight-
|
||||
@@ -7158,9 +7141,9 @@ static void bfq_update_depths(struct bfq_data *bfqd, struct sbitmap_queue *bt)
|
||||
* shortage.
|
||||
*/
|
||||
/* no more than ~18% of tags for async I/O */
|
||||
bfqd->word_depths[1][0] = max((depth * 3) >> 4, 1U);
|
||||
bfqd->async_depths[1][0] = max((nr_requests * 3) >> 4, 1U);
|
||||
/* no more than ~37% of tags for sync writes (~20% extra tags) */
|
||||
bfqd->word_depths[1][1] = max((depth * 6) >> 4, 1U);
|
||||
bfqd->async_depths[1][1] = max((nr_requests * 6) >> 4, 1U);
|
||||
}
|
||||
|
||||
static void bfq_depth_updated(struct blk_mq_hw_ctx *hctx)
|
||||
@@ -7232,22 +7215,16 @@ static void bfq_init_root_group(struct bfq_group *root_group,
|
||||
root_group->sched_data.bfq_class_idle_last_service = jiffies;
|
||||
}
|
||||
|
||||
static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
|
||||
static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
|
||||
{
|
||||
struct bfq_data *bfqd;
|
||||
struct elevator_queue *eq;
|
||||
unsigned int i;
|
||||
struct blk_independent_access_ranges *ia_ranges = q->disk->ia_ranges;
|
||||
|
||||
eq = elevator_alloc(q, e);
|
||||
if (!eq)
|
||||
bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node);
|
||||
if (!bfqd)
|
||||
return -ENOMEM;
|
||||
|
||||
bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node);
|
||||
if (!bfqd) {
|
||||
kobject_put(&eq->kobj);
|
||||
return -ENOMEM;
|
||||
}
|
||||
eq->elevator_data = bfqd;
|
||||
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
@@ -7405,7 +7382,6 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
|
||||
|
||||
out_free:
|
||||
kfree(bfqd);
|
||||
kobject_put(&eq->kobj);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
@@ -427,9 +427,6 @@ struct bfq_iocq_bfqq_data {
|
||||
*/
|
||||
bool saved_IO_bound;
|
||||
|
||||
u64 saved_io_start_time;
|
||||
u64 saved_tot_idle_time;
|
||||
|
||||
/*
|
||||
* Same purpose as the previous fields for the values of the
|
||||
* field keeping the queue's belonging to a large burst
|
||||
@@ -450,6 +447,9 @@ struct bfq_iocq_bfqq_data {
|
||||
*/
|
||||
unsigned int saved_weight;
|
||||
|
||||
u64 saved_io_start_time;
|
||||
u64 saved_tot_idle_time;
|
||||
|
||||
/*
|
||||
* Similar to previous fields: save wr information.
|
||||
*/
|
||||
@@ -457,13 +457,13 @@ struct bfq_iocq_bfqq_data {
|
||||
unsigned long saved_last_wr_start_finish;
|
||||
unsigned long saved_service_from_wr;
|
||||
unsigned long saved_wr_start_at_switch_to_srt;
|
||||
unsigned int saved_wr_cur_max_time;
|
||||
struct bfq_ttime saved_ttime;
|
||||
unsigned int saved_wr_cur_max_time;
|
||||
|
||||
/* Save also injection state */
|
||||
u64 saved_last_serv_time_ns;
|
||||
unsigned int saved_inject_limit;
|
||||
unsigned long saved_decrease_time_jif;
|
||||
u64 saved_last_serv_time_ns;
|
||||
|
||||
/* candidate queue for a stable merge (due to close creation time) */
|
||||
struct bfq_queue *stable_merge_bfqq;
|
||||
@@ -813,8 +813,7 @@ struct bfq_data {
|
||||
* Depth limits used in bfq_limit_depth (see comments on the
|
||||
* function)
|
||||
*/
|
||||
unsigned int word_depths[2][2];
|
||||
unsigned int full_depth_shift;
|
||||
unsigned int async_depths[2][2];
|
||||
|
||||
/*
|
||||
* Number of independent actuators. This is equal to 1 in
|
||||
|
||||
@@ -308,24 +308,23 @@ int __copy_io(unsigned long clone_flags, struct task_struct *tsk)
|
||||
|
||||
#ifdef CONFIG_BLK_ICQ
|
||||
/**
|
||||
* ioc_lookup_icq - lookup io_cq from ioc
|
||||
* ioc_lookup_icq - lookup io_cq from ioc in io issue path
|
||||
* @q: the associated request_queue
|
||||
*
|
||||
* Look up io_cq associated with @ioc - @q pair from @ioc. Must be called
|
||||
* with @q->queue_lock held.
|
||||
* from io issue path, either return NULL if current issue io to @q for the
|
||||
* first time, or return a valid icq.
|
||||
*/
|
||||
struct io_cq *ioc_lookup_icq(struct request_queue *q)
|
||||
{
|
||||
struct io_context *ioc = current->io_context;
|
||||
struct io_cq *icq;
|
||||
|
||||
lockdep_assert_held(&q->queue_lock);
|
||||
|
||||
/*
|
||||
* icq's are indexed from @ioc using radix tree and hint pointer,
|
||||
* both of which are protected with RCU. All removals are done
|
||||
* holding both q and ioc locks, and we're holding q lock - if we
|
||||
* find a icq which points to us, it's guaranteed to be valid.
|
||||
* both of which are protected with RCU, io issue path ensures that
|
||||
* both request_queue and current task are valid, the found icq
|
||||
* is guaranteed to be valid until the io is done.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
icq = rcu_dereference(ioc->icq_hint);
|
||||
@@ -419,10 +418,7 @@ struct io_cq *ioc_find_get_icq(struct request_queue *q)
|
||||
task_unlock(current);
|
||||
} else {
|
||||
get_io_context(ioc);
|
||||
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
icq = ioc_lookup_icq(q);
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
}
|
||||
|
||||
if (!icq) {
|
||||
|
||||
@@ -374,64 +374,17 @@ bool blk_mq_sched_try_insert_merge(struct request_queue *q, struct request *rq,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_mq_sched_try_insert_merge);
|
||||
|
||||
static int blk_mq_sched_alloc_map_and_rqs(struct request_queue *q,
|
||||
struct blk_mq_hw_ctx *hctx,
|
||||
unsigned int hctx_idx)
|
||||
{
|
||||
if (blk_mq_is_shared_tags(q->tag_set->flags)) {
|
||||
hctx->sched_tags = q->sched_shared_tags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
hctx->sched_tags = blk_mq_alloc_map_and_rqs(q->tag_set, hctx_idx,
|
||||
q->nr_requests);
|
||||
|
||||
if (!hctx->sched_tags)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void blk_mq_exit_sched_shared_tags(struct request_queue *queue)
|
||||
{
|
||||
blk_mq_free_rq_map(queue->sched_shared_tags);
|
||||
queue->sched_shared_tags = NULL;
|
||||
}
|
||||
|
||||
/* called in queue's release handler, tagset has gone away */
|
||||
static void blk_mq_sched_tags_teardown(struct request_queue *q, unsigned int flags)
|
||||
{
|
||||
struct blk_mq_hw_ctx *hctx;
|
||||
unsigned long i;
|
||||
|
||||
queue_for_each_hw_ctx(q, hctx, i) {
|
||||
if (hctx->sched_tags) {
|
||||
if (!blk_mq_is_shared_tags(flags))
|
||||
blk_mq_free_rq_map(hctx->sched_tags);
|
||||
hctx->sched_tags = NULL;
|
||||
}
|
||||
}
|
||||
queue_for_each_hw_ctx(q, hctx, i)
|
||||
hctx->sched_tags = NULL;
|
||||
|
||||
if (blk_mq_is_shared_tags(flags))
|
||||
blk_mq_exit_sched_shared_tags(q);
|
||||
}
|
||||
|
||||
static int blk_mq_init_sched_shared_tags(struct request_queue *queue)
|
||||
{
|
||||
struct blk_mq_tag_set *set = queue->tag_set;
|
||||
|
||||
/*
|
||||
* Set initial depth at max so that we don't need to reallocate for
|
||||
* updating nr_requests.
|
||||
*/
|
||||
queue->sched_shared_tags = blk_mq_alloc_map_and_rqs(set,
|
||||
BLK_MQ_NO_HCTX_IDX,
|
||||
MAX_SCHED_RQ);
|
||||
if (!queue->sched_shared_tags)
|
||||
return -ENOMEM;
|
||||
|
||||
blk_mq_tag_update_sched_shared_tags(queue);
|
||||
|
||||
return 0;
|
||||
q->sched_shared_tags = NULL;
|
||||
}
|
||||
|
||||
void blk_mq_sched_reg_debugfs(struct request_queue *q)
|
||||
@@ -458,8 +411,140 @@ void blk_mq_sched_unreg_debugfs(struct request_queue *q)
|
||||
mutex_unlock(&q->debugfs_mutex);
|
||||
}
|
||||
|
||||
void blk_mq_free_sched_tags(struct elevator_tags *et,
|
||||
struct blk_mq_tag_set *set)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
/* Shared tags are stored at index 0 in @tags. */
|
||||
if (blk_mq_is_shared_tags(set->flags))
|
||||
blk_mq_free_map_and_rqs(set, et->tags[0], BLK_MQ_NO_HCTX_IDX);
|
||||
else {
|
||||
for (i = 0; i < et->nr_hw_queues; i++)
|
||||
blk_mq_free_map_and_rqs(set, et->tags[i], i);
|
||||
}
|
||||
|
||||
kfree(et);
|
||||
}
|
||||
|
||||
void blk_mq_free_sched_tags_batch(struct xarray *et_table,
|
||||
struct blk_mq_tag_set *set)
|
||||
{
|
||||
struct request_queue *q;
|
||||
struct elevator_tags *et;
|
||||
|
||||
lockdep_assert_held_write(&set->update_nr_hwq_lock);
|
||||
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list) {
|
||||
/*
|
||||
* Accessing q->elevator without holding q->elevator_lock is
|
||||
* safe because we're holding here set->update_nr_hwq_lock in
|
||||
* the writer context. So, scheduler update/switch code (which
|
||||
* acquires the same lock but in the reader context) can't run
|
||||
* concurrently.
|
||||
*/
|
||||
if (q->elevator) {
|
||||
et = xa_load(et_table, q->id);
|
||||
if (unlikely(!et))
|
||||
WARN_ON_ONCE(1);
|
||||
else
|
||||
blk_mq_free_sched_tags(et, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set,
|
||||
unsigned int nr_hw_queues)
|
||||
{
|
||||
unsigned int nr_tags;
|
||||
int i;
|
||||
struct elevator_tags *et;
|
||||
gfp_t gfp = GFP_NOIO | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY;
|
||||
|
||||
if (blk_mq_is_shared_tags(set->flags))
|
||||
nr_tags = 1;
|
||||
else
|
||||
nr_tags = nr_hw_queues;
|
||||
|
||||
et = kmalloc(sizeof(struct elevator_tags) +
|
||||
nr_tags * sizeof(struct blk_mq_tags *), gfp);
|
||||
if (!et)
|
||||
return NULL;
|
||||
/*
|
||||
* Default to double of smaller one between hw queue_depth and
|
||||
* 128, since we don't split into sync/async like the old code
|
||||
* did. Additionally, this is a per-hw queue depth.
|
||||
*/
|
||||
et->nr_requests = 2 * min_t(unsigned int, set->queue_depth,
|
||||
BLKDEV_DEFAULT_RQ);
|
||||
et->nr_hw_queues = nr_hw_queues;
|
||||
|
||||
if (blk_mq_is_shared_tags(set->flags)) {
|
||||
/* Shared tags are stored at index 0 in @tags. */
|
||||
et->tags[0] = blk_mq_alloc_map_and_rqs(set, BLK_MQ_NO_HCTX_IDX,
|
||||
MAX_SCHED_RQ);
|
||||
if (!et->tags[0])
|
||||
goto out;
|
||||
} else {
|
||||
for (i = 0; i < et->nr_hw_queues; i++) {
|
||||
et->tags[i] = blk_mq_alloc_map_and_rqs(set, i,
|
||||
et->nr_requests);
|
||||
if (!et->tags[i])
|
||||
goto out_unwind;
|
||||
}
|
||||
}
|
||||
|
||||
return et;
|
||||
out_unwind:
|
||||
while (--i >= 0)
|
||||
blk_mq_free_map_and_rqs(set, et->tags[i], i);
|
||||
out:
|
||||
kfree(et);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int blk_mq_alloc_sched_tags_batch(struct xarray *et_table,
|
||||
struct blk_mq_tag_set *set, unsigned int nr_hw_queues)
|
||||
{
|
||||
struct request_queue *q;
|
||||
struct elevator_tags *et;
|
||||
gfp_t gfp = GFP_NOIO | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY;
|
||||
|
||||
lockdep_assert_held_write(&set->update_nr_hwq_lock);
|
||||
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list) {
|
||||
/*
|
||||
* Accessing q->elevator without holding q->elevator_lock is
|
||||
* safe because we're holding here set->update_nr_hwq_lock in
|
||||
* the writer context. So, scheduler update/switch code (which
|
||||
* acquires the same lock but in the reader context) can't run
|
||||
* concurrently.
|
||||
*/
|
||||
if (q->elevator) {
|
||||
et = blk_mq_alloc_sched_tags(set, nr_hw_queues);
|
||||
if (!et)
|
||||
goto out_unwind;
|
||||
if (xa_insert(et_table, q->id, et, gfp))
|
||||
goto out_free_tags;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
out_free_tags:
|
||||
blk_mq_free_sched_tags(et, set);
|
||||
out_unwind:
|
||||
list_for_each_entry_continue_reverse(q, &set->tag_list, tag_set_list) {
|
||||
if (q->elevator) {
|
||||
et = xa_load(et_table, q->id);
|
||||
if (et)
|
||||
blk_mq_free_sched_tags(et, set);
|
||||
}
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* caller must have a reference to @e, will grab another one if successful */
|
||||
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e,
|
||||
struct elevator_tags *et)
|
||||
{
|
||||
unsigned int flags = q->tag_set->flags;
|
||||
struct blk_mq_hw_ctx *hctx;
|
||||
@@ -467,36 +552,33 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||
unsigned long i;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Default to double of smaller one between hw queue_depth and 128,
|
||||
* since we don't split into sync/async like the old code did.
|
||||
* Additionally, this is a per-hw queue depth.
|
||||
*/
|
||||
q->nr_requests = 2 * min_t(unsigned int, q->tag_set->queue_depth,
|
||||
BLKDEV_DEFAULT_RQ);
|
||||
eq = elevator_alloc(q, e, et);
|
||||
if (!eq)
|
||||
return -ENOMEM;
|
||||
|
||||
q->nr_requests = et->nr_requests;
|
||||
|
||||
if (blk_mq_is_shared_tags(flags)) {
|
||||
ret = blk_mq_init_sched_shared_tags(q);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Shared tags are stored at index 0 in @et->tags. */
|
||||
q->sched_shared_tags = et->tags[0];
|
||||
blk_mq_tag_update_sched_shared_tags(q);
|
||||
}
|
||||
|
||||
queue_for_each_hw_ctx(q, hctx, i) {
|
||||
ret = blk_mq_sched_alloc_map_and_rqs(q, hctx, i);
|
||||
if (ret)
|
||||
goto err_free_map_and_rqs;
|
||||
if (blk_mq_is_shared_tags(flags))
|
||||
hctx->sched_tags = q->sched_shared_tags;
|
||||
else
|
||||
hctx->sched_tags = et->tags[i];
|
||||
}
|
||||
|
||||
ret = e->ops.init_sched(q, e);
|
||||
ret = e->ops.init_sched(q, eq);
|
||||
if (ret)
|
||||
goto err_free_map_and_rqs;
|
||||
goto out;
|
||||
|
||||
queue_for_each_hw_ctx(q, hctx, i) {
|
||||
if (e->ops.init_hctx) {
|
||||
ret = e->ops.init_hctx(hctx, i);
|
||||
if (ret) {
|
||||
eq = q->elevator;
|
||||
blk_mq_sched_free_rqs(q);
|
||||
blk_mq_exit_sched(q, eq);
|
||||
kobject_put(&eq->kobj);
|
||||
return ret;
|
||||
@@ -505,10 +587,9 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_free_map_and_rqs:
|
||||
blk_mq_sched_free_rqs(q);
|
||||
out:
|
||||
blk_mq_sched_tags_teardown(q, flags);
|
||||
|
||||
kobject_put(&eq->kobj);
|
||||
q->elevator = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,20 @@ void __blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx);
|
||||
|
||||
void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx);
|
||||
|
||||
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e);
|
||||
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e,
|
||||
struct elevator_tags *et);
|
||||
void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e);
|
||||
void blk_mq_sched_free_rqs(struct request_queue *q);
|
||||
|
||||
struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set,
|
||||
unsigned int nr_hw_queues);
|
||||
int blk_mq_alloc_sched_tags_batch(struct xarray *et_table,
|
||||
struct blk_mq_tag_set *set, unsigned int nr_hw_queues);
|
||||
void blk_mq_free_sched_tags(struct elevator_tags *et,
|
||||
struct blk_mq_tag_set *set);
|
||||
void blk_mq_free_sched_tags_batch(struct xarray *et_table,
|
||||
struct blk_mq_tag_set *set);
|
||||
|
||||
static inline void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
|
||||
|
||||
@@ -4974,12 +4974,13 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr)
|
||||
* Switch back to the elevator type stored in the xarray.
|
||||
*/
|
||||
static void blk_mq_elv_switch_back(struct request_queue *q,
|
||||
struct xarray *elv_tbl)
|
||||
struct xarray *elv_tbl, struct xarray *et_tbl)
|
||||
{
|
||||
struct elevator_type *e = xa_load(elv_tbl, q->id);
|
||||
struct elevator_tags *t = xa_load(et_tbl, q->id);
|
||||
|
||||
/* The elv_update_nr_hw_queues unfreezes the queue. */
|
||||
elv_update_nr_hw_queues(q, e);
|
||||
elv_update_nr_hw_queues(q, e, t);
|
||||
|
||||
/* Drop the reference acquired in blk_mq_elv_switch_none. */
|
||||
if (e)
|
||||
@@ -5031,7 +5032,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
|
||||
int prev_nr_hw_queues = set->nr_hw_queues;
|
||||
unsigned int memflags;
|
||||
int i;
|
||||
struct xarray elv_tbl;
|
||||
struct xarray elv_tbl, et_tbl;
|
||||
|
||||
lockdep_assert_held(&set->tag_list_lock);
|
||||
|
||||
@@ -5044,6 +5045,10 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
|
||||
|
||||
memflags = memalloc_noio_save();
|
||||
|
||||
xa_init(&et_tbl);
|
||||
if (blk_mq_alloc_sched_tags_batch(&et_tbl, set, nr_hw_queues) < 0)
|
||||
goto out_memalloc_restore;
|
||||
|
||||
xa_init(&elv_tbl);
|
||||
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list) {
|
||||
@@ -5087,7 +5092,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
|
||||
switch_back:
|
||||
/* The blk_mq_elv_switch_back unfreezes queue for us. */
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list)
|
||||
blk_mq_elv_switch_back(q, &elv_tbl);
|
||||
blk_mq_elv_switch_back(q, &elv_tbl, &et_tbl);
|
||||
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list) {
|
||||
blk_mq_sysfs_register_hctxs(q);
|
||||
@@ -5098,7 +5103,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
|
||||
}
|
||||
|
||||
xa_destroy(&elv_tbl);
|
||||
|
||||
xa_destroy(&et_tbl);
|
||||
out_memalloc_restore:
|
||||
memalloc_noio_restore(memflags);
|
||||
|
||||
/* Free the excess tags when nr_hw_queues shrink. */
|
||||
|
||||
@@ -62,16 +62,24 @@ EXPORT_SYMBOL(blk_set_stacking_limits);
|
||||
void blk_apply_bdi_limits(struct backing_dev_info *bdi,
|
||||
struct queue_limits *lim)
|
||||
{
|
||||
u64 io_opt = lim->io_opt;
|
||||
|
||||
/*
|
||||
* For read-ahead of large files to be effective, we need to read ahead
|
||||
* at least twice the optimal I/O size.
|
||||
* at least twice the optimal I/O size. For rotational devices that do
|
||||
* not report an optimal I/O size (e.g. ATA HDDs), use the maximum I/O
|
||||
* size to avoid falling back to the (rather inefficient) small default
|
||||
* read-ahead size.
|
||||
*
|
||||
* There is no hardware limitation for the read-ahead size and the user
|
||||
* might have increased the read-ahead size through sysfs, so don't ever
|
||||
* decrease it.
|
||||
*/
|
||||
if (!io_opt && (lim->features & BLK_FEAT_ROTATIONAL))
|
||||
io_opt = (u64)lim->max_sectors << SECTOR_SHIFT;
|
||||
|
||||
bdi->ra_pages = max3(bdi->ra_pages,
|
||||
lim->io_opt * 2 / PAGE_SIZE,
|
||||
io_opt * 2 >> PAGE_SHIFT,
|
||||
VM_READAHEAD_PAGES);
|
||||
bdi->io_pages = lim->max_sectors >> PAGE_SECTORS_SHIFT;
|
||||
}
|
||||
@@ -312,8 +320,12 @@ int blk_validate_limits(struct queue_limits *lim)
|
||||
pr_warn("Invalid logical block size (%d)\n", lim->logical_block_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (lim->physical_block_size < lim->logical_block_size)
|
||||
if (lim->physical_block_size < lim->logical_block_size) {
|
||||
lim->physical_block_size = lim->logical_block_size;
|
||||
} else if (!is_power_of_2(lim->physical_block_size)) {
|
||||
pr_warn("Invalid physical block size (%d)\n", lim->physical_block_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The minimum I/O size defaults to the physical block size unless
|
||||
@@ -388,12 +400,19 @@ int blk_validate_limits(struct queue_limits *lim)
|
||||
lim->max_discard_sectors =
|
||||
min(lim->max_hw_discard_sectors, lim->max_user_discard_sectors);
|
||||
|
||||
/*
|
||||
* When discard is not supported, discard_granularity should be reported
|
||||
* as 0 to userspace.
|
||||
*/
|
||||
if (lim->max_discard_sectors)
|
||||
lim->discard_granularity =
|
||||
max(lim->discard_granularity, lim->physical_block_size);
|
||||
else
|
||||
lim->discard_granularity = 0;
|
||||
|
||||
if (!lim->max_discard_segments)
|
||||
lim->max_discard_segments = 1;
|
||||
|
||||
if (lim->discard_granularity < lim->physical_block_size)
|
||||
lim->discard_granularity = lim->physical_block_size;
|
||||
|
||||
/*
|
||||
* By default there is no limit on the segment boundary alignment,
|
||||
* but if there is one it can't be smaller than the page size as
|
||||
@@ -849,7 +868,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
}
|
||||
|
||||
/* chunk_sectors a multiple of the physical block size? */
|
||||
if ((t->chunk_sectors << 9) & (t->physical_block_size - 1)) {
|
||||
if (t->chunk_sectors % (t->physical_block_size >> SECTOR_SHIFT)) {
|
||||
t->chunk_sectors = 0;
|
||||
t->flags |= BLK_FLAG_MISALIGNED;
|
||||
ret = -1;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "blk-crypto-internal.h"
|
||||
|
||||
struct elevator_type;
|
||||
struct elevator_tags;
|
||||
|
||||
/*
|
||||
* Default upper limit for the software max_sectors limit used for regular I/Os.
|
||||
@@ -330,7 +331,8 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list,
|
||||
|
||||
bool blk_insert_flush(struct request *rq);
|
||||
|
||||
void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e);
|
||||
void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e,
|
||||
struct elevator_tags *t);
|
||||
void elevator_set_default(struct request_queue *q);
|
||||
void elevator_set_none(struct request_queue *q);
|
||||
|
||||
|
||||
@@ -54,6 +54,8 @@ struct elv_change_ctx {
|
||||
struct elevator_queue *old;
|
||||
/* for registering new elevator */
|
||||
struct elevator_queue *new;
|
||||
/* holds sched tags data */
|
||||
struct elevator_tags *et;
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(elv_list_lock);
|
||||
@@ -132,7 +134,7 @@ static struct elevator_type *elevator_find_get(const char *name)
|
||||
static const struct kobj_type elv_ktype;
|
||||
|
||||
struct elevator_queue *elevator_alloc(struct request_queue *q,
|
||||
struct elevator_type *e)
|
||||
struct elevator_type *e, struct elevator_tags *et)
|
||||
{
|
||||
struct elevator_queue *eq;
|
||||
|
||||
@@ -145,10 +147,10 @@ struct elevator_queue *elevator_alloc(struct request_queue *q,
|
||||
kobject_init(&eq->kobj, &elv_ktype);
|
||||
mutex_init(&eq->sysfs_lock);
|
||||
hash_init(eq->hash);
|
||||
eq->et = et;
|
||||
|
||||
return eq;
|
||||
}
|
||||
EXPORT_SYMBOL(elevator_alloc);
|
||||
|
||||
static void elevator_release(struct kobject *kobj)
|
||||
{
|
||||
@@ -166,7 +168,6 @@ static void elevator_exit(struct request_queue *q)
|
||||
lockdep_assert_held(&q->elevator_lock);
|
||||
|
||||
ioc_clear_queue(q);
|
||||
blk_mq_sched_free_rqs(q);
|
||||
|
||||
mutex_lock(&e->sysfs_lock);
|
||||
blk_mq_exit_sched(q, e);
|
||||
@@ -592,7 +593,7 @@ static int elevator_switch(struct request_queue *q, struct elv_change_ctx *ctx)
|
||||
}
|
||||
|
||||
if (new_e) {
|
||||
ret = blk_mq_init_sched(q, new_e);
|
||||
ret = blk_mq_init_sched(q, new_e, ctx->et);
|
||||
if (ret)
|
||||
goto out_unfreeze;
|
||||
ctx->new = q->elevator;
|
||||
@@ -627,8 +628,10 @@ static void elv_exit_and_release(struct request_queue *q)
|
||||
elevator_exit(q);
|
||||
mutex_unlock(&q->elevator_lock);
|
||||
blk_mq_unfreeze_queue(q, memflags);
|
||||
if (e)
|
||||
if (e) {
|
||||
blk_mq_free_sched_tags(e->et, q->tag_set);
|
||||
kobject_put(&e->kobj);
|
||||
}
|
||||
}
|
||||
|
||||
static int elevator_change_done(struct request_queue *q,
|
||||
@@ -641,6 +644,7 @@ static int elevator_change_done(struct request_queue *q,
|
||||
&ctx->old->flags);
|
||||
|
||||
elv_unregister_queue(q, ctx->old);
|
||||
blk_mq_free_sched_tags(ctx->old->et, q->tag_set);
|
||||
kobject_put(&ctx->old->kobj);
|
||||
if (enable_wbt)
|
||||
wbt_enable_default(q->disk);
|
||||
@@ -659,9 +663,16 @@ static int elevator_change_done(struct request_queue *q,
|
||||
static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx)
|
||||
{
|
||||
unsigned int memflags;
|
||||
struct blk_mq_tag_set *set = q->tag_set;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&q->tag_set->update_nr_hwq_lock);
|
||||
lockdep_assert_held(&set->update_nr_hwq_lock);
|
||||
|
||||
if (strncmp(ctx->name, "none", 4)) {
|
||||
ctx->et = blk_mq_alloc_sched_tags(set, set->nr_hw_queues);
|
||||
if (!ctx->et)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memflags = blk_mq_freeze_queue(q);
|
||||
/*
|
||||
@@ -681,6 +692,11 @@ static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx)
|
||||
blk_mq_unfreeze_queue(q, memflags);
|
||||
if (!ret)
|
||||
ret = elevator_change_done(q, ctx);
|
||||
/*
|
||||
* Free sched tags if it's allocated but we couldn't switch elevator.
|
||||
*/
|
||||
if (ctx->et && !ctx->new)
|
||||
blk_mq_free_sched_tags(ctx->et, set);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -689,8 +705,10 @@ static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx)
|
||||
* The I/O scheduler depends on the number of hardware queues, this forces a
|
||||
* reattachment when nr_hw_queues changes.
|
||||
*/
|
||||
void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e)
|
||||
void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e,
|
||||
struct elevator_tags *t)
|
||||
{
|
||||
struct blk_mq_tag_set *set = q->tag_set;
|
||||
struct elv_change_ctx ctx = {};
|
||||
int ret = -ENODEV;
|
||||
|
||||
@@ -698,6 +716,7 @@ void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e)
|
||||
|
||||
if (e && !blk_queue_dying(q) && blk_queue_registered(q)) {
|
||||
ctx.name = e->elevator_name;
|
||||
ctx.et = t;
|
||||
|
||||
mutex_lock(&q->elevator_lock);
|
||||
/* force to reattach elevator after nr_hw_queue is updated */
|
||||
@@ -707,6 +726,11 @@ void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e)
|
||||
blk_mq_unfreeze_queue_nomemrestore(q);
|
||||
if (!ret)
|
||||
WARN_ON_ONCE(elevator_change_done(q, &ctx));
|
||||
/*
|
||||
* Free sched tags if it's allocated but we couldn't switch elevator.
|
||||
*/
|
||||
if (t && !ctx.new)
|
||||
blk_mq_free_sched_tags(t, set);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -23,8 +23,17 @@ enum elv_merge {
|
||||
struct blk_mq_alloc_data;
|
||||
struct blk_mq_hw_ctx;
|
||||
|
||||
struct elevator_tags {
|
||||
/* num. of hardware queues for which tags are allocated */
|
||||
unsigned int nr_hw_queues;
|
||||
/* depth used while allocating tags */
|
||||
unsigned int nr_requests;
|
||||
/* shared tag is stored at index 0 */
|
||||
struct blk_mq_tags *tags[];
|
||||
};
|
||||
|
||||
struct elevator_mq_ops {
|
||||
int (*init_sched)(struct request_queue *, struct elevator_type *);
|
||||
int (*init_sched)(struct request_queue *, struct elevator_queue *);
|
||||
void (*exit_sched)(struct elevator_queue *);
|
||||
int (*init_hctx)(struct blk_mq_hw_ctx *, unsigned int);
|
||||
void (*exit_hctx)(struct blk_mq_hw_ctx *, unsigned int);
|
||||
@@ -113,6 +122,7 @@ struct request *elv_rqhash_find(struct request_queue *q, sector_t offset);
|
||||
struct elevator_queue
|
||||
{
|
||||
struct elevator_type *type;
|
||||
struct elevator_tags *et;
|
||||
void *elevator_data;
|
||||
struct kobject kobj;
|
||||
struct mutex sysfs_lock;
|
||||
@@ -152,8 +162,8 @@ ssize_t elv_iosched_show(struct gendisk *disk, char *page);
|
||||
ssize_t elv_iosched_store(struct gendisk *disk, const char *page, size_t count);
|
||||
|
||||
extern bool elv_bio_merge_ok(struct request *, struct bio *);
|
||||
extern struct elevator_queue *elevator_alloc(struct request_queue *,
|
||||
struct elevator_type *);
|
||||
struct elevator_queue *elevator_alloc(struct request_queue *,
|
||||
struct elevator_type *, struct elevator_tags *);
|
||||
|
||||
/*
|
||||
* Helper functions.
|
||||
|
||||
@@ -157,10 +157,7 @@ struct kyber_queue_data {
|
||||
*/
|
||||
struct sbitmap_queue domain_tokens[KYBER_NUM_DOMAINS];
|
||||
|
||||
/*
|
||||
* Async request percentage, converted to per-word depth for
|
||||
* sbitmap_get_shallow().
|
||||
*/
|
||||
/* Number of allowed async requests. */
|
||||
unsigned int async_depth;
|
||||
|
||||
struct kyber_cpu_latency __percpu *cpu_latency;
|
||||
@@ -402,20 +399,13 @@ static struct kyber_queue_data *kyber_queue_data_alloc(struct request_queue *q)
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int kyber_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||
static int kyber_init_sched(struct request_queue *q, struct elevator_queue *eq)
|
||||
{
|
||||
struct kyber_queue_data *kqd;
|
||||
struct elevator_queue *eq;
|
||||
|
||||
eq = elevator_alloc(q, e);
|
||||
if (!eq)
|
||||
return -ENOMEM;
|
||||
|
||||
kqd = kyber_queue_data_alloc(q);
|
||||
if (IS_ERR(kqd)) {
|
||||
kobject_put(&eq->kobj);
|
||||
if (IS_ERR(kqd))
|
||||
return PTR_ERR(kqd);
|
||||
}
|
||||
|
||||
blk_stat_enable_accounting(q);
|
||||
|
||||
@@ -454,10 +444,8 @@ static void kyber_depth_updated(struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
struct kyber_queue_data *kqd = hctx->queue->elevator->elevator_data;
|
||||
struct blk_mq_tags *tags = hctx->sched_tags;
|
||||
unsigned int shift = tags->bitmap_tags.sb.shift;
|
||||
|
||||
kqd->async_depth = (1U << shift) * KYBER_ASYNC_PERCENT / 100U;
|
||||
|
||||
kqd->async_depth = hctx->queue->nr_requests * KYBER_ASYNC_PERCENT / 100U;
|
||||
sbitmap_queue_min_shallow_depth(&tags->bitmap_tags, kqd->async_depth);
|
||||
}
|
||||
|
||||
|
||||
@@ -487,20 +487,6 @@ static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
return rq;
|
||||
}
|
||||
|
||||
/*
|
||||
* 'depth' is a number in the range 1..INT_MAX representing a number of
|
||||
* requests. Scale it with a factor (1 << bt->sb.shift) / q->nr_requests since
|
||||
* 1..(1 << bt->sb.shift) is the range expected by sbitmap_get_shallow().
|
||||
* Values larger than q->nr_requests have the same effect as q->nr_requests.
|
||||
*/
|
||||
static int dd_to_word_depth(struct blk_mq_hw_ctx *hctx, unsigned int qdepth)
|
||||
{
|
||||
struct sbitmap_queue *bt = &hctx->sched_tags->bitmap_tags;
|
||||
const unsigned int nrr = hctx->queue->nr_requests;
|
||||
|
||||
return ((qdepth << bt->sb.shift) + nrr - 1) / nrr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by __blk_mq_alloc_request(). The shallow_depth value set by this
|
||||
* function is used by __blk_mq_get_tag().
|
||||
@@ -517,7 +503,7 @@ static void dd_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
|
||||
* Throttle asynchronous requests and writes such that these requests
|
||||
* do not block the allocation of synchronous requests.
|
||||
*/
|
||||
data->shallow_depth = dd_to_word_depth(data->hctx, dd->async_depth);
|
||||
data->shallow_depth = dd->async_depth;
|
||||
}
|
||||
|
||||
/* Called by blk_mq_update_nr_requests(). */
|
||||
@@ -568,20 +554,14 @@ static void dd_exit_sched(struct elevator_queue *e)
|
||||
/*
|
||||
* initialize elevator private data (deadline_data).
|
||||
*/
|
||||
static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||
static int dd_init_sched(struct request_queue *q, struct elevator_queue *eq)
|
||||
{
|
||||
struct deadline_data *dd;
|
||||
struct elevator_queue *eq;
|
||||
enum dd_prio prio;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
eq = elevator_alloc(q, e);
|
||||
if (!eq)
|
||||
return ret;
|
||||
|
||||
dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
|
||||
if (!dd)
|
||||
goto put_eq;
|
||||
return -ENOMEM;
|
||||
|
||||
eq->elevator_data = dd;
|
||||
|
||||
@@ -608,10 +588,6 @@ static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||
|
||||
q->elevator = eq;
|
||||
return 0;
|
||||
|
||||
put_eq:
|
||||
kobject_put(&eq->kobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1829,9 +1829,6 @@ static void hl_release_dmabuf(struct dma_buf *dmabuf)
|
||||
struct hl_dmabuf_priv *hl_dmabuf = dmabuf->priv;
|
||||
struct hl_ctx *ctx;
|
||||
|
||||
if (!hl_dmabuf)
|
||||
return;
|
||||
|
||||
ctx = hl_dmabuf->ctx;
|
||||
|
||||
if (hl_dmabuf->memhash_hnode)
|
||||
@@ -1859,7 +1856,12 @@ static int export_dmabuf(struct hl_ctx *ctx,
|
||||
{
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
struct hl_device *hdev = ctx->hdev;
|
||||
int rc, fd;
|
||||
CLASS(get_unused_fd, fd)(flags);
|
||||
|
||||
if (fd < 0) {
|
||||
dev_err(hdev->dev, "failed to get a file descriptor for a dma-buf, %d\n", fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
exp_info.ops = &habanalabs_dmabuf_ops;
|
||||
exp_info.size = total_size;
|
||||
@@ -1872,13 +1874,6 @@ static int export_dmabuf(struct hl_ctx *ctx,
|
||||
return PTR_ERR(hl_dmabuf->dmabuf);
|
||||
}
|
||||
|
||||
fd = dma_buf_fd(hl_dmabuf->dmabuf, flags);
|
||||
if (fd < 0) {
|
||||
dev_err(hdev->dev, "failed to get a file descriptor for a dma-buf, %d\n", fd);
|
||||
rc = fd;
|
||||
goto err_dma_buf_put;
|
||||
}
|
||||
|
||||
hl_dmabuf->ctx = ctx;
|
||||
hl_ctx_get(hl_dmabuf->ctx);
|
||||
atomic_inc(&ctx->hdev->dmabuf_export_cnt);
|
||||
@@ -1890,13 +1885,9 @@ static int export_dmabuf(struct hl_ctx *ctx,
|
||||
get_file(ctx->hpriv->file_priv->filp);
|
||||
|
||||
*dmabuf_fd = fd;
|
||||
fd_install(take_fd(fd), hl_dmabuf->dmabuf->file);
|
||||
|
||||
return 0;
|
||||
|
||||
err_dma_buf_put:
|
||||
hl_dmabuf->dmabuf->priv = NULL;
|
||||
dma_buf_put(hl_dmabuf->dmabuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int validate_export_params_common(struct hl_device *hdev, u64 addr, u64 size, u64 offset)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
struct regmap_irq_chip_data {
|
||||
struct mutex lock;
|
||||
struct lock_class_key lock_key;
|
||||
struct irq_chip irq_chip;
|
||||
|
||||
struct regmap *map;
|
||||
@@ -801,7 +802,13 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
mutex_init(&d->lock);
|
||||
/*
|
||||
* If one regmap-irq is the parent of another then we'll try
|
||||
* to lock the child with the parent locked, use an explicit
|
||||
* lock_key so lockdep can figure out what's going on.
|
||||
*/
|
||||
lockdep_register_key(&d->lock_key);
|
||||
mutex_init_with_key(&d->lock, &d->lock_key);
|
||||
|
||||
for (i = 0; i < chip->num_irqs; i++)
|
||||
d->mask_buf_def[chip->irqs[i].reg_offset / map->reg_stride]
|
||||
@@ -816,7 +823,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
d->mask_buf[i],
|
||||
chip->irq_drv_data);
|
||||
if (ret)
|
||||
goto err_alloc;
|
||||
goto err_mutex;
|
||||
}
|
||||
|
||||
if (chip->mask_base && !chip->handle_mask_sync) {
|
||||
@@ -827,7 +834,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
if (ret) {
|
||||
dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
|
||||
reg, ret);
|
||||
goto err_alloc;
|
||||
goto err_mutex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,7 +845,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
if (ret) {
|
||||
dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
|
||||
reg, ret);
|
||||
goto err_alloc;
|
||||
goto err_mutex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -855,7 +862,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
if (ret != 0) {
|
||||
dev_err(map->dev, "Failed to read IRQ status: %d\n",
|
||||
ret);
|
||||
goto err_alloc;
|
||||
goto err_mutex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -879,7 +886,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
if (ret != 0) {
|
||||
dev_err(map->dev, "Failed to ack 0x%x: %d\n",
|
||||
reg, ret);
|
||||
goto err_alloc;
|
||||
goto err_mutex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -901,7 +908,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
if (ret != 0) {
|
||||
dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
|
||||
reg, ret);
|
||||
goto err_alloc;
|
||||
goto err_mutex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -910,7 +917,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
if (chip->status_is_level) {
|
||||
ret = read_irq_data(d);
|
||||
if (ret < 0)
|
||||
goto err_alloc;
|
||||
goto err_mutex;
|
||||
|
||||
memcpy(d->prev_status_buf, d->status_buf,
|
||||
array_size(d->chip->num_regs, sizeof(d->prev_status_buf[0])));
|
||||
@@ -918,7 +925,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
|
||||
ret = regmap_irq_create_domain(fwnode, irq_base, chip, d);
|
||||
if (ret)
|
||||
goto err_alloc;
|
||||
goto err_mutex;
|
||||
|
||||
ret = request_threaded_irq(irq, NULL, regmap_irq_thread,
|
||||
irq_flags | IRQF_ONESHOT,
|
||||
@@ -935,6 +942,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
||||
|
||||
err_domain:
|
||||
/* Should really dispose of the domain but... */
|
||||
err_mutex:
|
||||
mutex_destroy(&d->lock);
|
||||
lockdep_unregister_key(&d->lock_key);
|
||||
err_alloc:
|
||||
kfree(d->type_buf);
|
||||
kfree(d->type_buf_def);
|
||||
@@ -1027,6 +1037,8 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
|
||||
kfree(d->config_buf[i]);
|
||||
kfree(d->config_buf);
|
||||
}
|
||||
mutex_destroy(&d->lock);
|
||||
lockdep_unregister_key(&d->lock_key);
|
||||
kfree(d);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_del_irq_chip);
|
||||
|
||||
@@ -186,7 +186,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
chip->request = bcma_gpio_request;
|
||||
chip->free = bcma_gpio_free;
|
||||
chip->get = bcma_gpio_get_value;
|
||||
chip->set_rv = bcma_gpio_set_value;
|
||||
chip->set = bcma_gpio_set_value;
|
||||
chip->direction_input = bcma_gpio_direction_input;
|
||||
chip->direction_output = bcma_gpio_direction_output;
|
||||
chip->parent = bus->dev;
|
||||
|
||||
@@ -700,6 +700,8 @@ static void zloop_free_disk(struct gendisk *disk)
|
||||
struct zloop_device *zlo = disk->private_data;
|
||||
unsigned int i;
|
||||
|
||||
blk_mq_free_tag_set(&zlo->tag_set);
|
||||
|
||||
for (i = 0; i < zlo->nr_zones; i++) {
|
||||
struct zloop_zone *zone = &zlo->zones[i];
|
||||
|
||||
@@ -1080,7 +1082,6 @@ static int zloop_ctl_remove(struct zloop_options *opts)
|
||||
|
||||
del_gendisk(zlo->disk);
|
||||
put_disk(zlo->disk);
|
||||
blk_mq_free_tag_set(&zlo->tag_set);
|
||||
|
||||
pr_info("Removed device %d\n", opts->id);
|
||||
|
||||
|
||||
@@ -263,6 +263,14 @@ config EFI_COCO_SECRET
|
||||
virt/coco/efi_secret module to access the secrets, which in turn
|
||||
allows userspace programs to access the injected secrets.
|
||||
|
||||
config OVMF_DEBUG_LOG
|
||||
bool "Expose OVMF firmware debug log via sysfs"
|
||||
depends on EFI
|
||||
help
|
||||
Recent OVMF versions (edk2-stable202508 + newer) can write
|
||||
their debug log to a memory buffer. This driver exposes the
|
||||
log content via sysfs (/sys/firmware/efi/ovmf_debug_log).
|
||||
|
||||
config UNACCEPTED_MEMORY
|
||||
bool
|
||||
depends on EFI_STUB
|
||||
|
||||
@@ -29,6 +29,7 @@ obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o
|
||||
obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o
|
||||
obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o
|
||||
obj-$(CONFIG_LOAD_UEFI_KEYS) += mokvar-table.o
|
||||
obj-$(CONFIG_OVMF_DEBUG_LOG) += ovmf-debug-log.o
|
||||
|
||||
obj-$(CONFIG_SYSFB) += sysfb_efi.o
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ struct efi __read_mostly efi = {
|
||||
.esrt = EFI_INVALID_TABLE_ADDR,
|
||||
.tpm_log = EFI_INVALID_TABLE_ADDR,
|
||||
.tpm_final_log = EFI_INVALID_TABLE_ADDR,
|
||||
.ovmf_debug_log = EFI_INVALID_TABLE_ADDR,
|
||||
#ifdef CONFIG_LOAD_UEFI_KEYS
|
||||
.mokvar_table = EFI_INVALID_TABLE_ADDR,
|
||||
#endif
|
||||
@@ -473,6 +474,10 @@ static int __init efisubsys_init(void)
|
||||
platform_device_register_simple("efi_secret", 0, NULL, 0);
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_OVMF_DEBUG_LOG) &&
|
||||
efi.ovmf_debug_log != EFI_INVALID_TABLE_ADDR)
|
||||
ovmf_log_probe(efi.ovmf_debug_log);
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_group:
|
||||
@@ -617,6 +622,9 @@ static const efi_config_table_type_t common_tables[] __initconst = {
|
||||
{LINUX_EFI_MEMRESERVE_TABLE_GUID, &mem_reserve, "MEMRESERVE" },
|
||||
{LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD" },
|
||||
{EFI_RT_PROPERTIES_TABLE_GUID, &rt_prop, "RTPROP" },
|
||||
#ifdef CONFIG_OVMF_DEBUG_LOG
|
||||
{OVMF_MEMORY_LOG_TABLE_GUID, &efi.ovmf_debug_log, "OvmfDebugLog" },
|
||||
#endif
|
||||
#ifdef CONFIG_EFI_RCI2_TABLE
|
||||
{DELLEMC_EFI_RCI2_TABLE_GUID, &rci2_table_phys },
|
||||
#endif
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h> /* For CONSOLE_LOGLEVEL_* */
|
||||
#include <linux/kern_levels.h>
|
||||
#include <asm/efi.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
|
||||
int efi_loglevel = LOGLEVEL_NOTICE;
|
||||
|
||||
/**
|
||||
* efi_char16_puts() - Write a UCS-2 encoded string to the console
|
||||
|
||||
111
drivers/firmware/efi/ovmf-debug-log.c
Normal file
111
drivers/firmware/efi/ovmf-debug-log.c
Normal file
@@ -0,0 +1,111 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
#define OVMF_DEBUG_LOG_MAGIC1 0x3167646d666d766f // "ovmfmdg1"
|
||||
#define OVMF_DEBUG_LOG_MAGIC2 0x3267646d666d766f // "ovmfmdg2"
|
||||
|
||||
struct ovmf_debug_log_header {
|
||||
u64 magic1;
|
||||
u64 magic2;
|
||||
u64 hdr_size;
|
||||
u64 log_size;
|
||||
u64 lock; // edk2 spinlock
|
||||
u64 head_off;
|
||||
u64 tail_off;
|
||||
u64 truncated;
|
||||
u8 fw_version[128];
|
||||
};
|
||||
|
||||
static struct ovmf_debug_log_header *hdr;
|
||||
static u8 *logbuf;
|
||||
static u64 logbufsize;
|
||||
|
||||
static ssize_t ovmf_log_read(struct file *filp, struct kobject *kobj,
|
||||
const struct bin_attribute *attr, char *buf,
|
||||
loff_t offset, size_t count)
|
||||
{
|
||||
u64 start, end;
|
||||
|
||||
start = hdr->head_off + offset;
|
||||
if (hdr->head_off > hdr->tail_off && start >= hdr->log_size)
|
||||
start -= hdr->log_size;
|
||||
|
||||
end = start + count;
|
||||
if (start > hdr->tail_off) {
|
||||
if (end > hdr->log_size)
|
||||
end = hdr->log_size;
|
||||
} else {
|
||||
if (end > hdr->tail_off)
|
||||
end = hdr->tail_off;
|
||||
}
|
||||
|
||||
if (start > logbufsize || end > logbufsize)
|
||||
return 0;
|
||||
if (start >= end)
|
||||
return 0;
|
||||
|
||||
memcpy(buf, logbuf + start, end - start);
|
||||
return end - start;
|
||||
}
|
||||
|
||||
static struct bin_attribute ovmf_log_bin_attr = {
|
||||
.attr = {
|
||||
.name = "ovmf_debug_log",
|
||||
.mode = 0444,
|
||||
},
|
||||
.read = ovmf_log_read,
|
||||
};
|
||||
|
||||
int __init ovmf_log_probe(unsigned long ovmf_debug_log_table)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
u64 size;
|
||||
|
||||
/* map + verify header */
|
||||
hdr = memremap(ovmf_debug_log_table, sizeof(*hdr), MEMREMAP_WB);
|
||||
if (!hdr) {
|
||||
pr_err("OVMF debug log: header map failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hdr->magic1 != OVMF_DEBUG_LOG_MAGIC1 ||
|
||||
hdr->magic2 != OVMF_DEBUG_LOG_MAGIC2) {
|
||||
printk(KERN_ERR "OVMF debug log: magic mismatch\n");
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
size = hdr->hdr_size + hdr->log_size;
|
||||
pr_info("OVMF debug log: firmware version: \"%s\"\n", hdr->fw_version);
|
||||
pr_info("OVMF debug log: buffer size: %lluk\n", size / 1024);
|
||||
|
||||
/* map complete log buffer */
|
||||
memunmap(hdr);
|
||||
hdr = memremap(ovmf_debug_log_table, size, MEMREMAP_WB);
|
||||
if (!hdr) {
|
||||
pr_err("OVMF debug log: buffer map failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
logbuf = (void *)hdr + hdr->hdr_size;
|
||||
logbufsize = hdr->log_size;
|
||||
|
||||
ovmf_log_bin_attr.size = size;
|
||||
ret = sysfs_create_bin_file(efi_kobj, &ovmf_log_bin_attr);
|
||||
if (ret != 0) {
|
||||
pr_err("OVMF debug log: sysfs register failed\n");
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unmap:
|
||||
memunmap(hdr);
|
||||
return ret;
|
||||
}
|
||||
@@ -141,8 +141,8 @@ static int gen_74x164_probe(struct spi_device *spi)
|
||||
chip->gpio_chip.label = spi->modalias;
|
||||
chip->gpio_chip.direction_output = gen_74x164_direction_output;
|
||||
chip->gpio_chip.get = gen_74x164_get_value;
|
||||
chip->gpio_chip.set_rv = gen_74x164_set_value;
|
||||
chip->gpio_chip.set_multiple_rv = gen_74x164_set_multiple;
|
||||
chip->gpio_chip.set = gen_74x164_set_value;
|
||||
chip->gpio_chip.set_multiple = gen_74x164_set_multiple;
|
||||
chip->gpio_chip.base = -1;
|
||||
chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
|
||||
chip->gpio_chip.can_sleep = true;
|
||||
|
||||
@@ -430,7 +430,7 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios,
|
||||
chip->direction_input = adnp_gpio_direction_input;
|
||||
chip->direction_output = adnp_gpio_direction_output;
|
||||
chip->get = adnp_gpio_get;
|
||||
chip->set_rv = adnp_gpio_set;
|
||||
chip->set = adnp_gpio_set;
|
||||
chip->can_sleep = true;
|
||||
|
||||
if (IS_ENABLED(CONFIG_DEBUG_FS))
|
||||
|
||||
@@ -122,7 +122,7 @@ static int adp5520_gpio_probe(struct platform_device *pdev)
|
||||
gc->direction_input = adp5520_gpio_direction_input;
|
||||
gc->direction_output = adp5520_gpio_direction_output;
|
||||
gc->get = adp5520_gpio_get_value;
|
||||
gc->set_rv = adp5520_gpio_set_value;
|
||||
gc->set = adp5520_gpio_set_value;
|
||||
gc->can_sleep = true;
|
||||
|
||||
gc->base = pdata->gpio_start;
|
||||
|
||||
@@ -428,7 +428,7 @@ static int adp5585_gpio_probe(struct platform_device *pdev)
|
||||
gc->direction_input = adp5585_gpio_direction_input;
|
||||
gc->direction_output = adp5585_gpio_direction_output;
|
||||
gc->get = adp5585_gpio_get_value;
|
||||
gc->set_rv = adp5585_gpio_set_value;
|
||||
gc->set = adp5585_gpio_set_value;
|
||||
gc->set_config = adp5585_gpio_set_config;
|
||||
gc->request = adp5585_gpio_request;
|
||||
gc->free = adp5585_gpio_free;
|
||||
|
||||
@@ -534,8 +534,8 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
|
||||
chip->direction_output = gpio_fwd_direction_output;
|
||||
chip->get = gpio_fwd_get;
|
||||
chip->get_multiple = gpio_fwd_get_multiple_locked;
|
||||
chip->set_rv = gpio_fwd_set;
|
||||
chip->set_multiple_rv = gpio_fwd_set_multiple_locked;
|
||||
chip->set = gpio_fwd_set;
|
||||
chip->set_multiple = gpio_fwd_set_multiple_locked;
|
||||
chip->to_irq = gpio_fwd_to_irq;
|
||||
chip->base = -1;
|
||||
chip->ngpio = ngpios;
|
||||
|
||||
@@ -69,7 +69,7 @@ static const struct gpio_chip altr_a10sr_gc = {
|
||||
.label = "altr_a10sr_gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.get = altr_a10sr_gpio_get,
|
||||
.set_rv = altr_a10sr_gpio_set,
|
||||
.set = altr_a10sr_gpio_set,
|
||||
.direction_input = altr_a10sr_gpio_direction_input,
|
||||
.direction_output = altr_a10sr_gpio_direction_output,
|
||||
.can_sleep = true,
|
||||
|
||||
@@ -259,7 +259,7 @@ static int altera_gpio_probe(struct platform_device *pdev)
|
||||
altera_gc->gc.direction_input = altera_gpio_direction_input;
|
||||
altera_gc->gc.direction_output = altera_gpio_direction_output;
|
||||
altera_gc->gc.get = altera_gpio_get;
|
||||
altera_gc->gc.set_rv = altera_gpio_set;
|
||||
altera_gc->gc.set = altera_gpio_set;
|
||||
altera_gc->gc.owner = THIS_MODULE;
|
||||
altera_gc->gc.parent = &pdev->dev;
|
||||
altera_gc->gc.base = -1;
|
||||
|
||||
@@ -165,7 +165,7 @@ static int amd_fch_gpio_probe(struct platform_device *pdev)
|
||||
priv->gc.direction_output = amd_fch_gpio_direction_output;
|
||||
priv->gc.get_direction = amd_fch_gpio_get_direction;
|
||||
priv->gc.get = amd_fch_gpio_get;
|
||||
priv->gc.set_rv = amd_fch_gpio_set;
|
||||
priv->gc.set = amd_fch_gpio_set;
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ static struct amd_gpio gp = {
|
||||
.ngpio = 32,
|
||||
.request = amd_gpio_request,
|
||||
.free = amd_gpio_free,
|
||||
.set_rv = amd_gpio_set,
|
||||
.set = amd_gpio_set,
|
||||
.get = amd_gpio_get,
|
||||
.direction_output = amd_gpio_dirout,
|
||||
.direction_input = amd_gpio_dirin,
|
||||
|
||||
@@ -138,7 +138,7 @@ static const struct gpio_chip template_chip = {
|
||||
.direction_input = arizona_gpio_direction_in,
|
||||
.get = arizona_gpio_get,
|
||||
.direction_output = arizona_gpio_direction_out,
|
||||
.set_rv = arizona_gpio_set,
|
||||
.set = arizona_gpio_set,
|
||||
.can_sleep = true,
|
||||
};
|
||||
|
||||
|
||||
@@ -596,7 +596,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
|
||||
gpio->chip.request = NULL;
|
||||
gpio->chip.free = NULL;
|
||||
gpio->chip.get = aspeed_sgpio_get;
|
||||
gpio->chip.set_rv = aspeed_sgpio_set;
|
||||
gpio->chip.set = aspeed_sgpio_set;
|
||||
gpio->chip.set_config = aspeed_sgpio_set_config;
|
||||
gpio->chip.label = dev_name(&pdev->dev);
|
||||
gpio->chip.base = -1;
|
||||
|
||||
@@ -1352,7 +1352,7 @@ static int aspeed_gpio_probe(struct platform_device *pdev)
|
||||
gpio->chip.request = aspeed_gpio_request;
|
||||
gpio->chip.free = aspeed_gpio_free;
|
||||
gpio->chip.get = aspeed_gpio_get;
|
||||
gpio->chip.set_rv = aspeed_gpio_set;
|
||||
gpio->chip.set = aspeed_gpio_set;
|
||||
gpio->chip.set_config = aspeed_gpio_set_config;
|
||||
gpio->chip.label = dev_name(&pdev->dev);
|
||||
gpio->chip.base = -1;
|
||||
|
||||
@@ -339,7 +339,7 @@ static const struct gpio_chip template_chip = {
|
||||
.direction_input = bcm_kona_gpio_direction_input,
|
||||
.get = bcm_kona_gpio_get,
|
||||
.direction_output = bcm_kona_gpio_direction_output,
|
||||
.set_rv = bcm_kona_gpio_set,
|
||||
.set = bcm_kona_gpio_set,
|
||||
.set_config = bcm_kona_gpio_set_config,
|
||||
.to_irq = bcm_kona_gpio_to_irq,
|
||||
.base = 0,
|
||||
|
||||
@@ -85,7 +85,7 @@ static const struct gpio_chip bd71815gpo_chip = {
|
||||
.owner = THIS_MODULE,
|
||||
.get = bd71815gpo_get,
|
||||
.get_direction = bd71815gpo_direction_get,
|
||||
.set_rv = bd71815gpo_set,
|
||||
.set = bd71815gpo_set,
|
||||
.set_config = bd71815_gpio_set_config,
|
||||
.can_sleep = true,
|
||||
};
|
||||
|
||||
@@ -109,7 +109,7 @@ static int bd71828_probe(struct platform_device *pdev)
|
||||
bdgpio->gpio.set_config = bd71828_gpio_set_config;
|
||||
bdgpio->gpio.can_sleep = true;
|
||||
bdgpio->gpio.get = bd71828_gpio_get;
|
||||
bdgpio->gpio.set_rv = bd71828_gpio_set;
|
||||
bdgpio->gpio.set = bd71828_gpio_set;
|
||||
bdgpio->gpio.base = -1;
|
||||
|
||||
/*
|
||||
|
||||
@@ -88,7 +88,7 @@ static const struct gpio_chip template_chip = {
|
||||
.direction_input = bd9571mwv_gpio_direction_input,
|
||||
.direction_output = bd9571mwv_gpio_direction_output,
|
||||
.get = bd9571mwv_gpio_get,
|
||||
.set_rv = bd9571mwv_gpio_set,
|
||||
.set = bd9571mwv_gpio_set,
|
||||
.base = -1,
|
||||
.ngpio = 2,
|
||||
.can_sleep = true,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user