mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 05:55:44 +02:00
Linux 5.8-rc6
-----BEGIN PGP SIGNATURE----- iQFSBAABCAA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAl8UzA4eHHRvcnZhbGRz QGxpbnV4LWZvdW5kYXRpb24ub3JnAAoJEHm+PkMAQRiGQ7cH/3v+Gv+SmHJCvaT2 CSu0+7okVnYbY3UTb3hykk7/aOqb6284KjxR03r0CWFzsEsZVhC5pvvruASSiMQg Pi04sLqv6CsGLHd1n+pl4AUYEaxq6k4KS3uU3HHSWxrahDDApQoRUx2F8lpOxyj8 RiwnoO60IMPA7IFJqzcZuFqsgdxqiiYvnzT461KX8Mrw6fyMXeR2KAj2NwMX8dZN At21Sf8+LSoh6q2HnugfiUd/jR10XbfxIIx2lXgIinb15GXgWydEQVrDJ7cUV7ix Jd0S+dtOtp+lWtFHDoyjjqqsMV7+G8i/rFNZoxSkyZqsUTaKzaR6JD3moSyoYZgG 0+eXO4A= =9EpR -----END PGP SIGNATURE----- Merge 5.8-rc6 into android-mainline Linux 5.8-rc6 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I136c3cfef1f692806b9c9e09c917744c10523a59
This commit is contained in:
commit
73a11b0961
|
|
@ -583,8 +583,8 @@ When the NFS export feature is enabled, all directory index entries are
|
|||
verified on mount time to check that upper file handles are not stale.
|
||||
This verification may cause significant overhead in some cases.
|
||||
|
||||
Note: the mount options index=off,nfs_export=on are conflicting and will
|
||||
result in an error.
|
||||
Note: the mount options index=off,nfs_export=on are conflicting for a
|
||||
read-write mount and will result in an error.
|
||||
|
||||
|
||||
Testsuite
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ request buffers are not in memory. The operating system handles the fault by
|
|||
updating CSB with the following data:
|
||||
|
||||
csb.flags = CSB_V;
|
||||
csb.cc = CSB_CC_TRANSLATION;
|
||||
csb.cc = CSB_CC_FAULT_ADDRESS;
|
||||
csb.ce = CSB_CE_TERMINATION;
|
||||
csb.address = fault_address;
|
||||
|
||||
|
|
|
|||
|
|
@ -5022,7 +5022,6 @@ F: drivers/mfd/da91??-*.c
|
|||
F: drivers/pinctrl/pinctrl-da90??.c
|
||||
F: drivers/power/supply/da9052-battery.c
|
||||
F: drivers/power/supply/da91??-*.c
|
||||
F: drivers/regulator/da903x.c
|
||||
F: drivers/regulator/da9???-regulator.[ch]
|
||||
F: drivers/regulator/slg51000-regulator.[ch]
|
||||
F: drivers/rtc/rtc-da90??.c
|
||||
|
|
@ -5112,7 +5111,7 @@ M: Vinod Koul <vkoul@kernel.org>
|
|||
L: dmaengine@vger.kernel.org
|
||||
S: Maintained
|
||||
Q: https://patchwork.kernel.org/project/linux-dmaengine/list/
|
||||
T: git git://git.infradead.org/users/vkoul/slave-dma.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git
|
||||
F: Documentation/devicetree/bindings/dma/
|
||||
F: Documentation/driver-api/dmaengine/
|
||||
F: drivers/dma/
|
||||
|
|
@ -17520,7 +17519,7 @@ F: Documentation/admin-guide/ufs.rst
|
|||
F: fs/ufs/
|
||||
|
||||
UHID USERSPACE HID IO DRIVER
|
||||
M: David Herrmann <dh.herrmann@googlemail.com>
|
||||
M: David Rheinsberg <david.rheinsberg@gmail.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hid/uhid.c
|
||||
|
|
@ -18479,7 +18478,7 @@ S: Maintained
|
|||
F: drivers/rtc/rtc-sd3078.c
|
||||
|
||||
WIIMOTE HID DRIVER
|
||||
M: David Herrmann <dh.herrmann@googlemail.com>
|
||||
M: David Rheinsberg <david.rheinsberg@gmail.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hid/hid-wiimote*
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 5
|
||||
PATCHLEVEL = 8
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc6
|
||||
NAME = Kleptomaniac Octopus
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -1540,8 +1540,9 @@ target-module@cc000 { /* 0x481cc000, ap 50 46.0 */
|
|||
reg = <0xcc020 0x4>;
|
||||
reg-names = "rev";
|
||||
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
|
||||
clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>,
|
||||
<&dcan0_fck>;
|
||||
clock-names = "fck", "osc";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0xcc000 0x2000>;
|
||||
|
|
@ -1549,6 +1550,8 @@ target-module@cc000 { /* 0x481cc000, ap 50 46.0 */
|
|||
dcan0: can@0 {
|
||||
compatible = "ti,am4372-d_can", "ti,am3352-d_can";
|
||||
reg = <0x0 0x2000>;
|
||||
clocks = <&dcan0_fck>;
|
||||
clock-names = "fck";
|
||||
syscon-raminit = <&scm_conf 0x644 0>;
|
||||
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
|
|
@ -1560,8 +1563,9 @@ target-module@d0000 { /* 0x481d0000, ap 52 3a.0 */
|
|||
reg = <0xd0020 0x4>;
|
||||
reg-names = "rev";
|
||||
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
|
||||
clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>,
|
||||
<&dcan1_fck>;
|
||||
clock-names = "fck", "osc";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0xd0000 0x2000>;
|
||||
|
|
@ -1569,6 +1573,8 @@ target-module@d0000 { /* 0x481d0000, ap 52 3a.0 */
|
|||
dcan1: can@0 {
|
||||
compatible = "ti,am4372-d_can", "ti,am3352-d_can";
|
||||
reg = <0x0 0x2000>;
|
||||
clocks = <&dcan1_fck>;
|
||||
clock-name = "fck";
|
||||
syscon-raminit = <&scm_conf 0x644 1>;
|
||||
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ sound-digital {
|
|||
simple-audio-card,frame-master = <&sound_codec>;
|
||||
|
||||
sound_cpu: simple-audio-card,cpu {
|
||||
sound-dai = <&ssi2>;
|
||||
sound-dai = <&ssi1>;
|
||||
};
|
||||
|
||||
sound_codec: simple-audio-card,codec {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ / {
|
|||
#size-cells = <1>;
|
||||
interrupt-parent = <&gic>;
|
||||
|
||||
L2: l2-cache-controller@c4200000 {
|
||||
L2: cache-controller@c4200000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0xc4200000 0x1000>;
|
||||
cache-unified;
|
||||
|
|
|
|||
|
|
@ -105,6 +105,14 @@ proximity_sensor {
|
|||
linux,code = <SW_FRONT_PROXIMITY>;
|
||||
linux,can-disable;
|
||||
};
|
||||
|
||||
machine_cover {
|
||||
label = "Machine Cover";
|
||||
gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; /* 160 */
|
||||
linux,input-type = <EV_SW>;
|
||||
linux,code = <SW_MACHINE_COVER>;
|
||||
linux,can-disable;
|
||||
};
|
||||
};
|
||||
|
||||
isp1707: isp1707 {
|
||||
|
|
@ -819,10 +827,6 @@ &mmc1 {
|
|||
pinctrl-0 = <&mmc1_pins>;
|
||||
vmmc-supply = <&vmmc1>;
|
||||
bus-width = <4>;
|
||||
/* For debugging, it is often good idea to remove this GPIO.
|
||||
It means you can remove back cover (to reboot by removing
|
||||
battery) and still use the MMC card. */
|
||||
cd-gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; /* 160 */
|
||||
};
|
||||
|
||||
/* most boards use vaux3, only some old versions use vmmc2 instead */
|
||||
|
|
|
|||
|
|
@ -726,7 +726,7 @@ ocram-ecc@ffd08144 {
|
|||
};
|
||||
};
|
||||
|
||||
L2: l2-cache@fffef000 {
|
||||
L2: cache-controller@fffef000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0xfffef000 0x1000>;
|
||||
interrupts = <0 38 0x04>;
|
||||
|
|
|
|||
|
|
@ -636,7 +636,7 @@ sdr: sdr@ffcfb100 {
|
|||
reg = <0xffcfb100 0x80>;
|
||||
};
|
||||
|
||||
L2: l2-cache@fffff000 {
|
||||
L2: cache-controller@fffff000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0xfffff000 0x1000>;
|
||||
interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
|
|
|||
|
|
@ -289,6 +289,6 @@ struct platform_device *__init imx_add_spi_imx(
|
|||
const struct spi_imx_master *pdata);
|
||||
|
||||
struct platform_device *imx_add_imx_dma(char *name, resource_size_t iobase,
|
||||
int irq, int irq_err);
|
||||
int irq);
|
||||
struct platform_device *imx_add_imx_sdma(char *name,
|
||||
resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ struct platform_device *__init mxc_register_gpio(char *name, int id,
|
|||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
unsigned int nres;
|
||||
|
||||
return platform_device_register_resndata(&mxc_aips_bus,
|
||||
name, id, res, ARRAY_SIZE(res), NULL, 0);
|
||||
nres = irq_high ? ARRAY_SIZE(res) : ARRAY_SIZE(res) - 1;
|
||||
return platform_device_register_resndata(&mxc_aips_bus, name, id, res, nres, NULL, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include "devices-common.h"
|
||||
|
||||
struct platform_device __init __maybe_unused *imx_add_imx_dma(char *name,
|
||||
resource_size_t iobase, int irq, int irq_err)
|
||||
resource_size_t iobase, int irq)
|
||||
{
|
||||
struct resource res[] = {
|
||||
{
|
||||
|
|
@ -17,10 +17,6 @@ struct platform_device __init __maybe_unused *imx_add_imx_dma(char *name,
|
|||
.start = irq,
|
||||
.end = irq,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}, {
|
||||
.start = irq_err,
|
||||
.end = irq_err,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -78,8 +78,7 @@ void __init imx21_soc_init(void)
|
|||
mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
|
||||
|
||||
pinctrl_provide_dummies();
|
||||
imx_add_imx_dma("imx21-dma", MX21_DMA_BASE_ADDR,
|
||||
MX21_INT_DMACH0, 0); /* No ERR irq */
|
||||
imx_add_imx_dma("imx21-dma", MX21_DMA_BASE_ADDR, MX21_INT_DMACH0);
|
||||
platform_device_register_simple("imx21-audmux", 0, imx21_audmux_res,
|
||||
ARRAY_SIZE(imx21_audmux_res));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,8 +79,7 @@ void __init imx27_soc_init(void)
|
|||
mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
|
||||
|
||||
pinctrl_provide_dummies();
|
||||
imx_add_imx_dma("imx27-dma", MX27_DMA_BASE_ADDR,
|
||||
MX27_INT_DMACH0, 0); /* No ERR irq */
|
||||
imx_add_imx_dma("imx27-dma", MX27_DMA_BASE_ADDR, MX27_INT_DMACH0);
|
||||
/* imx27 has the imx21 type audmux */
|
||||
platform_device_register_simple("imx21-audmux", 0, imx27_audmux_res,
|
||||
ARRAY_SIZE(imx27_audmux_res));
|
||||
|
|
|
|||
|
|
@ -3435,7 +3435,7 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
|
|||
regs = ioremap(data->module_pa,
|
||||
data->module_size);
|
||||
if (!regs)
|
||||
return -ENOMEM;
|
||||
goto out_free_sysc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3445,13 +3445,13 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
|
|||
if (oh->class->name && strcmp(oh->class->name, data->name)) {
|
||||
class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL);
|
||||
if (!class)
|
||||
return -ENOMEM;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
if (list_empty(&oh->slave_ports)) {
|
||||
oi = kcalloc(1, sizeof(*oi), GFP_KERNEL);
|
||||
if (!oi)
|
||||
return -ENOMEM;
|
||||
goto out_free_class;
|
||||
|
||||
/*
|
||||
* Note that we assume interconnect interface clocks will be
|
||||
|
|
@ -3478,6 +3478,14 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
|
|||
spin_unlock_irqrestore(&oh->_lock, flags);
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_class:
|
||||
kfree(class);
|
||||
out_unmap:
|
||||
iounmap(regs);
|
||||
out_free_sysc:
|
||||
kfree(sysc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static const struct omap_hwmod_reset omap24xx_reset_quirks[] = {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ psci {
|
|||
method = "smc";
|
||||
};
|
||||
|
||||
intc: intc@fffc1000 {
|
||||
intc: interrupt-controller@fffc1000 {
|
||||
compatible = "arm,gic-400", "arm,cortex-a15-gic";
|
||||
#interrupt-cells = <3>;
|
||||
interrupt-controller;
|
||||
|
|
@ -302,7 +302,7 @@ mmc: dwmmc0@ff808000 {
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
nand: nand@ffb90000 {
|
||||
nand: nand-controller@ffb90000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "altr,socfpga-denali-nand";
|
||||
|
|
@ -445,7 +445,7 @@ timer3: timer3@ffd00100 {
|
|||
clock-names = "timer";
|
||||
};
|
||||
|
||||
uart0: serial0@ffc02000 {
|
||||
uart0: serial@ffc02000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0xffc02000 0x100>;
|
||||
interrupts = <0 108 4>;
|
||||
|
|
@ -456,7 +456,7 @@ uart0: serial0@ffc02000 {
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
uart1: serial1@ffc02100 {
|
||||
uart1: serial@ffc02100 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0xffc02100 0x100>;
|
||||
interrupts = <0 109 4>;
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ rtc@68 {
|
|||
};
|
||||
|
||||
&qspi {
|
||||
status = "okay";
|
||||
flash@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ rtc@68 {
|
|||
};
|
||||
|
||||
&qspi {
|
||||
status = "okay";
|
||||
flash@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
@ -211,12 +212,12 @@ partitions {
|
|||
|
||||
qspi_boot: partition@0 {
|
||||
label = "Boot and fpga data";
|
||||
reg = <0x0 0x034B0000>;
|
||||
reg = <0x0 0x03FE0000>;
|
||||
};
|
||||
|
||||
qspi_rootfs: partition@4000000 {
|
||||
qspi_rootfs: partition@3FE0000 {
|
||||
label = "Root Filesystem - JFFS2";
|
||||
reg = <0x034B0000 0x0EB50000>;
|
||||
reg = <0x03FE0000 0x0C020000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/sound/meson-aiu.h>
|
||||
|
||||
#include "meson-gxl-s905x.dtsi"
|
||||
#include "meson-gxl-s805x.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "libretech,aml-s805x-ac", "amlogic,s805x",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
#include "meson-gxl-s905x.dtsi"
|
||||
#include "meson-gxl-s805x.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "amlogic,p241", "amlogic,s805x", "amlogic,meson-gxl";
|
||||
|
|
|
|||
24
arch/arm64/boot/dts/amlogic/meson-gxl-s805x.dtsi
Normal file
24
arch/arm64/boot/dts/amlogic/meson-gxl-s805x.dtsi
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 BayLibre SAS
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include "meson-gxl-s905x.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "amlogic,s805x", "amlogic,meson-gxl";
|
||||
};
|
||||
|
||||
/* The S805X Package doesn't seem to handle the 744MHz OPP correctly */
|
||||
&mali {
|
||||
assigned-clocks = <&clkc CLKID_MALI_0_SEL>,
|
||||
<&clkc CLKID_MALI_0>,
|
||||
<&clkc CLKID_MALI>; /* Glitch free mux */
|
||||
assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>,
|
||||
<0>, /* Do Nothing */
|
||||
<&clkc CLKID_MALI_0>;
|
||||
assigned-clock-rates = <0>, /* Do Nothing */
|
||||
<666666666>,
|
||||
<0>; /* Do Nothing */
|
||||
};
|
||||
|
|
@ -337,6 +337,11 @@ clkc: clock-controller {
|
|||
};
|
||||
};
|
||||
|
||||
&hwrng {
|
||||
clocks = <&clkc CLKID_RNG0>;
|
||||
clock-names = "core";
|
||||
};
|
||||
|
||||
&i2c_A {
|
||||
clocks = <&clkc CLKID_I2C>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ &watchdog0 {
|
|||
};
|
||||
|
||||
&qspi {
|
||||
status = "okay";
|
||||
flash@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ CONFIG_HOTPLUG_PCI=y
|
|||
CONFIG_HOTPLUG_PCI_ACPI=y
|
||||
CONFIG_PCI_AARDVARK=y
|
||||
CONFIG_PCI_TEGRA=y
|
||||
CONFIG_PCIE_RCAR=y
|
||||
CONFIG_PCIE_RCAR_HOST=y
|
||||
CONFIG_PCI_HOST_GENERIC=y
|
||||
CONFIG_PCI_XGENE=y
|
||||
CONFIG_PCIE_ALTERA=y
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ void disable_debug_monitors(enum dbg_active_el el);
|
|||
|
||||
void user_rewind_single_step(struct task_struct *task);
|
||||
void user_fastforward_single_step(struct task_struct *task);
|
||||
void user_regs_reset_single_step(struct user_pt_regs *regs,
|
||||
struct task_struct *task);
|
||||
|
||||
void kernel_enable_single_step(struct pt_regs *regs);
|
||||
void kernel_disable_single_step(void);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ static inline long syscall_get_error(struct task_struct *task,
|
|||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long error = regs->regs[0];
|
||||
|
||||
if (is_compat_thread(task_thread_info(task)))
|
||||
error = sign_extend64(error, 31);
|
||||
|
||||
return IS_ERR_VALUE(error) ? error : 0;
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +51,13 @@ static inline void syscall_set_return_value(struct task_struct *task,
|
|||
struct pt_regs *regs,
|
||||
int error, long val)
|
||||
{
|
||||
regs->regs[0] = (long) error ? error : val;
|
||||
if (error)
|
||||
val = error;
|
||||
|
||||
if (is_compat_thread(task_thread_info(task)))
|
||||
val = lower_32_bits(val);
|
||||
|
||||
regs->regs[0] = val;
|
||||
}
|
||||
|
||||
#define SYSCALL_MAX_ARGS 6
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ void arch_release_task_struct(struct task_struct *tsk);
|
|||
#define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU)
|
||||
#define _TIF_UPROBE (1 << TIF_UPROBE)
|
||||
#define _TIF_FSCHECK (1 << TIF_FSCHECK)
|
||||
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
|
||||
#define _TIF_32BIT (1 << TIF_32BIT)
|
||||
#define _TIF_SVE (1 << TIF_SVE)
|
||||
|
||||
|
|
|
|||
|
|
@ -141,17 +141,20 @@ postcore_initcall(debug_monitors_init);
|
|||
/*
|
||||
* Single step API and exception handling.
|
||||
*/
|
||||
static void set_regs_spsr_ss(struct pt_regs *regs)
|
||||
static void set_user_regs_spsr_ss(struct user_pt_regs *regs)
|
||||
{
|
||||
regs->pstate |= DBG_SPSR_SS;
|
||||
}
|
||||
NOKPROBE_SYMBOL(set_regs_spsr_ss);
|
||||
NOKPROBE_SYMBOL(set_user_regs_spsr_ss);
|
||||
|
||||
static void clear_regs_spsr_ss(struct pt_regs *regs)
|
||||
static void clear_user_regs_spsr_ss(struct user_pt_regs *regs)
|
||||
{
|
||||
regs->pstate &= ~DBG_SPSR_SS;
|
||||
}
|
||||
NOKPROBE_SYMBOL(clear_regs_spsr_ss);
|
||||
NOKPROBE_SYMBOL(clear_user_regs_spsr_ss);
|
||||
|
||||
#define set_regs_spsr_ss(r) set_user_regs_spsr_ss(&(r)->user_regs)
|
||||
#define clear_regs_spsr_ss(r) clear_user_regs_spsr_ss(&(r)->user_regs)
|
||||
|
||||
static DEFINE_SPINLOCK(debug_hook_lock);
|
||||
static LIST_HEAD(user_step_hook);
|
||||
|
|
@ -391,17 +394,26 @@ void user_rewind_single_step(struct task_struct *task)
|
|||
* If single step is active for this thread, then set SPSR.SS
|
||||
* to 1 to avoid returning to the active-pending state.
|
||||
*/
|
||||
if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP))
|
||||
if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
|
||||
set_regs_spsr_ss(task_pt_regs(task));
|
||||
}
|
||||
NOKPROBE_SYMBOL(user_rewind_single_step);
|
||||
|
||||
void user_fastforward_single_step(struct task_struct *task)
|
||||
{
|
||||
if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP))
|
||||
if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
|
||||
clear_regs_spsr_ss(task_pt_regs(task));
|
||||
}
|
||||
|
||||
void user_regs_reset_single_step(struct user_pt_regs *regs,
|
||||
struct task_struct *task)
|
||||
{
|
||||
if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
|
||||
set_user_regs_spsr_ss(regs);
|
||||
else
|
||||
clear_user_regs_spsr_ss(regs);
|
||||
}
|
||||
|
||||
/* Kernel API */
|
||||
void kernel_enable_single_step(struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1811,19 +1811,42 @@ static void tracehook_report_syscall(struct pt_regs *regs,
|
|||
unsigned long saved_reg;
|
||||
|
||||
/*
|
||||
* A scratch register (ip(r12) on AArch32, x7 on AArch64) is
|
||||
* used to denote syscall entry/exit:
|
||||
* We have some ABI weirdness here in the way that we handle syscall
|
||||
* exit stops because we indicate whether or not the stop has been
|
||||
* signalled from syscall entry or syscall exit by clobbering a general
|
||||
* purpose register (ip/r12 for AArch32, x7 for AArch64) in the tracee
|
||||
* and restoring its old value after the stop. This means that:
|
||||
*
|
||||
* - Any writes by the tracer to this register during the stop are
|
||||
* ignored/discarded.
|
||||
*
|
||||
* - The actual value of the register is not available during the stop,
|
||||
* so the tracer cannot save it and restore it later.
|
||||
*
|
||||
* - Syscall stops behave differently to seccomp and pseudo-step traps
|
||||
* (the latter do not nobble any registers).
|
||||
*/
|
||||
regno = (is_compat_task() ? 12 : 7);
|
||||
saved_reg = regs->regs[regno];
|
||||
regs->regs[regno] = dir;
|
||||
|
||||
if (dir == PTRACE_SYSCALL_EXIT)
|
||||
if (dir == PTRACE_SYSCALL_ENTER) {
|
||||
if (tracehook_report_syscall_entry(regs))
|
||||
forget_syscall(regs);
|
||||
regs->regs[regno] = saved_reg;
|
||||
} else if (!test_thread_flag(TIF_SINGLESTEP)) {
|
||||
tracehook_report_syscall_exit(regs, 0);
|
||||
else if (tracehook_report_syscall_entry(regs))
|
||||
forget_syscall(regs);
|
||||
regs->regs[regno] = saved_reg;
|
||||
} else {
|
||||
regs->regs[regno] = saved_reg;
|
||||
|
||||
regs->regs[regno] = saved_reg;
|
||||
/*
|
||||
* Signal a pseudo-step exception since we are stepping but
|
||||
* tracer modifications to the registers may have rewound the
|
||||
* state machine.
|
||||
*/
|
||||
tracehook_report_syscall_exit(regs, 1);
|
||||
}
|
||||
}
|
||||
|
||||
int syscall_trace_enter(struct pt_regs *regs)
|
||||
|
|
@ -1833,12 +1856,12 @@ int syscall_trace_enter(struct pt_regs *regs)
|
|||
if (flags & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE)) {
|
||||
tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
|
||||
if (!in_syscall(regs) || (flags & _TIF_SYSCALL_EMU))
|
||||
return -1;
|
||||
return NO_SYSCALL;
|
||||
}
|
||||
|
||||
/* Do the secure computing after ptrace; failures should be fast. */
|
||||
if (secure_computing() == -1)
|
||||
return -1;
|
||||
return NO_SYSCALL;
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
|
||||
trace_sys_enter(regs, regs->syscallno);
|
||||
|
|
@ -1851,12 +1874,14 @@ int syscall_trace_enter(struct pt_regs *regs)
|
|||
|
||||
void syscall_trace_exit(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags = READ_ONCE(current_thread_info()->flags);
|
||||
|
||||
audit_syscall_exit(regs);
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
|
||||
if (flags & _TIF_SYSCALL_TRACEPOINT)
|
||||
trace_sys_exit(regs, regs_return_value(regs));
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE))
|
||||
if (flags & (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP))
|
||||
tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
|
||||
|
||||
rseq_syscall(regs);
|
||||
|
|
@ -1934,8 +1959,8 @@ static int valid_native_regs(struct user_pt_regs *regs)
|
|||
*/
|
||||
int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task)
|
||||
{
|
||||
if (!test_tsk_thread_flag(task, TIF_SINGLESTEP))
|
||||
regs->pstate &= ~DBG_SPSR_SS;
|
||||
/* https://lore.kernel.org/lkml/20191118131525.GA4180@willie-the-truck */
|
||||
user_regs_reset_single_step(regs, task);
|
||||
|
||||
if (is_compat_thread(task_thread_info(task)))
|
||||
return valid_compat_regs(regs);
|
||||
|
|
|
|||
|
|
@ -800,7 +800,6 @@ static void setup_restart_syscall(struct pt_regs *regs)
|
|||
*/
|
||||
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int usig = ksig->sig;
|
||||
int ret;
|
||||
|
|
@ -824,14 +823,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
|||
*/
|
||||
ret |= !valid_user_regs(®s->user_regs, current);
|
||||
|
||||
/*
|
||||
* Fast forward the stepping logic so we step into the signal
|
||||
* handler.
|
||||
*/
|
||||
if (!ret)
|
||||
user_fastforward_single_step(tsk);
|
||||
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
/* Step into the signal handler if we are stepping */
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ static void invoke_syscall(struct pt_regs *regs, unsigned int scno,
|
|||
ret = do_ni_syscall(regs, scno);
|
||||
}
|
||||
|
||||
if (is_compat_task())
|
||||
ret = lower_32_bits(ret);
|
||||
|
||||
regs->regs[0] = ret;
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +124,21 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
|
|||
user_exit();
|
||||
|
||||
if (has_syscall_work(flags)) {
|
||||
/* set default errno for user-issued syscall(-1) */
|
||||
/*
|
||||
* The de-facto standard way to skip a system call using ptrace
|
||||
* is to set the system call to -1 (NO_SYSCALL) and set x0 to a
|
||||
* suitable error code for consumption by userspace. However,
|
||||
* this cannot be distinguished from a user-issued syscall(-1)
|
||||
* and so we must set x0 to -ENOSYS here in case the tracer doesn't
|
||||
* issue the skip and we fall into trace_exit with x0 preserved.
|
||||
*
|
||||
* This is slightly odd because it also means that if a tracer
|
||||
* sets the system call number to -1 but does not initialise x0,
|
||||
* then x0 will be preserved for all system calls apart from a
|
||||
* user-issued syscall(-1). However, requesting a skip and not
|
||||
* setting the return value is unlikely to do anything sensible
|
||||
* anyway.
|
||||
*/
|
||||
if (scno == NO_SYSCALL)
|
||||
regs->regs[0] = -ENOSYS;
|
||||
scno = syscall_trace_enter(regs);
|
||||
|
|
@ -139,7 +156,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
|
|||
if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
|
||||
local_daif_mask();
|
||||
flags = current_thread_info()->flags;
|
||||
if (!has_syscall_work(flags)) {
|
||||
if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP)) {
|
||||
/*
|
||||
* We're off to userspace, where interrupts are
|
||||
* always enabled after we restore the flags from
|
||||
|
|
|
|||
|
|
@ -627,9 +627,10 @@ static int bridge_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
domain = irq_domain_create_hierarchy(parent, 0, 8, fn,
|
||||
&bridge_domain_ops, NULL);
|
||||
irq_domain_free_fwnode(fn);
|
||||
if (!domain)
|
||||
if (!domain) {
|
||||
irq_domain_free_fwnode(fn);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pci_set_flags(PCI_PROBE_ONLY);
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ struct coprocessor_completion_block {
|
|||
#define CSB_CC_CHAIN (37)
|
||||
#define CSB_CC_SEQUENCE (38)
|
||||
#define CSB_CC_HW (39)
|
||||
/* P9 DD2 NX Workbook 3.2 (Table 4-36): Address translation fault */
|
||||
#define CSB_CC_FAULT_ADDRESS (250)
|
||||
|
||||
#define CSB_SIZE (0x10)
|
||||
#define CSB_ALIGN CSB_SIZE
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ static void *__init alloc_shared_lppaca(unsigned long size, unsigned long align,
|
|||
* This is very early in boot, so no harm done if the kernel crashes at
|
||||
* this point.
|
||||
*/
|
||||
BUG_ON(shared_lppaca_size >= shared_lppaca_total_size);
|
||||
BUG_ON(shared_lppaca_size > shared_lppaca_total_size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -354,12 +354,14 @@ static bool pkey_access_permitted(int pkey, bool write, bool execute)
|
|||
u64 amr;
|
||||
|
||||
pkey_shift = pkeyshift(pkey);
|
||||
if (execute && !(read_iamr() & (IAMR_EX_BIT << pkey_shift)))
|
||||
return true;
|
||||
if (execute)
|
||||
return !(read_iamr() & (IAMR_EX_BIT << pkey_shift));
|
||||
|
||||
amr = read_amr(); /* Delay reading amr until absolutely needed */
|
||||
return ((!write && !(amr & (AMR_RD_BIT << pkey_shift))) ||
|
||||
(write && !(amr & (AMR_WR_BIT << pkey_shift))));
|
||||
amr = read_amr();
|
||||
if (write)
|
||||
return !(amr & (AMR_WR_BIT << pkey_shift));
|
||||
|
||||
return !(amr & (AMR_RD_BIT << pkey_shift));
|
||||
}
|
||||
|
||||
bool arch_pte_access_permitted(u64 pte, bool write, bool execute)
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ static void update_csb(struct vas_window *window,
|
|||
csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
|
||||
|
||||
memset(&csb, 0, sizeof(csb));
|
||||
csb.cc = CSB_CC_TRANSLATION;
|
||||
csb.cc = CSB_CC_FAULT_ADDRESS;
|
||||
csb.ce = CSB_CE_TERMINATION;
|
||||
csb.cs = 0;
|
||||
csb.count = 0;
|
||||
|
|
|
|||
|
|
@ -58,8 +58,16 @@ do { \
|
|||
* The AQ/RL pair provides a RCpc critical section, but there's not really any
|
||||
* way we can take advantage of that here because the ordering is only enforced
|
||||
* on that one lock. Thus, we're just doing a full fence.
|
||||
*
|
||||
* Since we allow writeX to be called from preemptive regions we need at least
|
||||
* an "o" in the predecessor set to ensure device writes are visible before the
|
||||
* task is marked as available for scheduling on a new hart. While I don't see
|
||||
* any concrete reason we need a full IO fence, it seems safer to just upgrade
|
||||
* this in order to avoid any IO crossing a scheduling boundary. In both
|
||||
* instances the scheduler pairs this with an mb(), so nothing is necessary on
|
||||
* the new hart.
|
||||
*/
|
||||
#define smp_mb__after_spinlock() RISCV_FENCE(rw,rw)
|
||||
#define smp_mb__after_spinlock() RISCV_FENCE(iorw,iorw)
|
||||
|
||||
#include <asm-generic/barrier.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
#include <linux/const.h>
|
||||
|
||||
/* thread information allocation */
|
||||
#ifdef CONFIG_64BIT
|
||||
#define THREAD_SIZE_ORDER (2)
|
||||
#else
|
||||
#define THREAD_SIZE_ORDER (1)
|
||||
#endif
|
||||
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ endif
|
|||
|
||||
vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
|
||||
|
||||
vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
|
||||
vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
|
||||
efi-obj-$(CONFIG_EFI_STUB) = $(objtree)/drivers/firmware/efi/libstub/lib.a
|
||||
|
||||
# The compressed kernel is built with -fPIC/-fPIE so that a boot loader
|
||||
# can place it anywhere in memory and it will still run. However, since
|
||||
|
|
@ -115,7 +115,7 @@ endef
|
|||
quiet_cmd_check-and-link-vmlinux = LD $@
|
||||
cmd_check-and-link-vmlinux = $(cmd_check_data_rel); $(cmd_ld)
|
||||
|
||||
$(obj)/vmlinux: $(vmlinux-objs-y) FORCE
|
||||
$(obj)/vmlinux: $(vmlinux-objs-y) $(efi-obj-y) FORCE
|
||||
$(call if_changed,check-and-link-vmlinux)
|
||||
|
||||
OBJCOPYFLAGS_vmlinux.bin := -R .comment -S
|
||||
|
|
|
|||
|
|
@ -7,12 +7,20 @@ KASAN_SANITIZE := n
|
|||
UBSAN_SANITIZE := n
|
||||
KCOV_INSTRUMENT := n
|
||||
|
||||
CFLAGS_REMOVE_common.o = $(CC_FLAGS_FTRACE) -fstack-protector -fstack-protector-strong
|
||||
CFLAGS_REMOVE_syscall_32.o = $(CC_FLAGS_FTRACE) -fstack-protector -fstack-protector-strong
|
||||
CFLAGS_REMOVE_syscall_64.o = $(CC_FLAGS_FTRACE) -fstack-protector -fstack-protector-strong
|
||||
CFLAGS_REMOVE_common.o = $(CC_FLAGS_FTRACE)
|
||||
CFLAGS_REMOVE_syscall_64.o = $(CC_FLAGS_FTRACE)
|
||||
CFLAGS_REMOVE_syscall_32.o = $(CC_FLAGS_FTRACE)
|
||||
CFLAGS_REMOVE_syscall_x32.o = $(CC_FLAGS_FTRACE)
|
||||
|
||||
CFLAGS_common.o += -fno-stack-protector
|
||||
CFLAGS_syscall_64.o += -fno-stack-protector
|
||||
CFLAGS_syscall_32.o += -fno-stack-protector
|
||||
CFLAGS_syscall_x32.o += -fno-stack-protector
|
||||
|
||||
CFLAGS_syscall_64.o += $(call cc-option,-Wno-override-init,)
|
||||
CFLAGS_syscall_32.o += $(call cc-option,-Wno-override-init,)
|
||||
CFLAGS_syscall_x32.o += $(call cc-option,-Wno-override-init,)
|
||||
|
||||
obj-y := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
|
||||
obj-y += common.o
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
#include <trace/events/syscalls.h>
|
||||
|
||||
/* Check that the stack and regs on entry from user mode are sane. */
|
||||
static void check_user_regs(struct pt_regs *regs)
|
||||
static noinstr void check_user_regs(struct pt_regs *regs)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) {
|
||||
/*
|
||||
|
|
@ -294,7 +294,7 @@ static void __prepare_exit_to_usermode(struct pt_regs *regs)
|
|||
#endif
|
||||
}
|
||||
|
||||
__visible noinstr void prepare_exit_to_usermode(struct pt_regs *regs)
|
||||
static noinstr void prepare_exit_to_usermode(struct pt_regs *regs)
|
||||
{
|
||||
instrumentation_begin();
|
||||
__prepare_exit_to_usermode(regs);
|
||||
|
|
|
|||
|
|
@ -469,16 +469,15 @@ __visible noinstr void func(struct pt_regs *regs, \
|
|||
.align 8
|
||||
SYM_CODE_START(irq_entries_start)
|
||||
vector=FIRST_EXTERNAL_VECTOR
|
||||
pos = .
|
||||
.rept (FIRST_SYSTEM_VECTOR - FIRST_EXTERNAL_VECTOR)
|
||||
UNWIND_HINT_IRET_REGS
|
||||
0 :
|
||||
.byte 0x6a, vector
|
||||
jmp asm_common_interrupt
|
||||
nop
|
||||
/* Ensure that the above is 8 bytes max */
|
||||
. = pos + 8
|
||||
pos=pos+8
|
||||
vector=vector+1
|
||||
. = 0b + 8
|
||||
vector = vector+1
|
||||
.endr
|
||||
SYM_CODE_END(irq_entries_start)
|
||||
|
||||
|
|
@ -486,16 +485,15 @@ SYM_CODE_END(irq_entries_start)
|
|||
.align 8
|
||||
SYM_CODE_START(spurious_entries_start)
|
||||
vector=FIRST_SYSTEM_VECTOR
|
||||
pos = .
|
||||
.rept (NR_VECTORS - FIRST_SYSTEM_VECTOR)
|
||||
UNWIND_HINT_IRET_REGS
|
||||
0 :
|
||||
.byte 0x6a, vector
|
||||
jmp asm_spurious_interrupt
|
||||
nop
|
||||
/* Ensure that the above is 8 bytes max */
|
||||
. = pos + 8
|
||||
pos=pos+8
|
||||
vector=vector+1
|
||||
. = 0b + 8
|
||||
vector = vector+1
|
||||
.endr
|
||||
SYM_CODE_END(spurious_entries_start)
|
||||
#endif
|
||||
|
|
@ -553,7 +551,7 @@ DECLARE_IDTENTRY_RAW(X86_TRAP_MC, exc_machine_check);
|
|||
|
||||
/* NMI */
|
||||
DECLARE_IDTENTRY_NMI(X86_TRAP_NMI, exc_nmi);
|
||||
#ifdef CONFIG_XEN_PV
|
||||
#if defined(CONFIG_XEN_PV) && defined(CONFIG_X86_64)
|
||||
DECLARE_IDTENTRY_RAW(X86_TRAP_NMI, xenpv_exc_nmi);
|
||||
#endif
|
||||
|
||||
|
|
@ -563,7 +561,7 @@ DECLARE_IDTENTRY_DEBUG(X86_TRAP_DB, exc_debug);
|
|||
#else
|
||||
DECLARE_IDTENTRY_RAW(X86_TRAP_DB, exc_debug);
|
||||
#endif
|
||||
#ifdef CONFIG_XEN_PV
|
||||
#if defined(CONFIG_XEN_PV) && defined(CONFIG_X86_64)
|
||||
DECLARE_IDTENTRY_RAW(X86_TRAP_DB, xenpv_exc_debug);
|
||||
#endif
|
||||
|
||||
|
|
@ -626,8 +624,8 @@ DECLARE_IDTENTRY_SYSVEC(POSTED_INTR_NESTED_VECTOR, sysvec_kvm_posted_intr_nested
|
|||
|
||||
#if IS_ENABLED(CONFIG_HYPERV)
|
||||
DECLARE_IDTENTRY_SYSVEC(HYPERVISOR_CALLBACK_VECTOR, sysvec_hyperv_callback);
|
||||
DECLARE_IDTENTRY_SYSVEC(HYPERVISOR_REENLIGHTENMENT_VECTOR, sysvec_hyperv_reenlightenment);
|
||||
DECLARE_IDTENTRY_SYSVEC(HYPERVISOR_STIMER0_VECTOR, sysvec_hyperv_stimer0);
|
||||
DECLARE_IDTENTRY_SYSVEC(HYPERV_REENLIGHTENMENT_VECTOR, sysvec_hyperv_reenlightenment);
|
||||
DECLARE_IDTENTRY_SYSVEC(HYPERV_STIMER0_VECTOR, sysvec_hyperv_stimer0);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACRN_GUEST)
|
||||
|
|
|
|||
|
|
@ -19,12 +19,28 @@ struct task_struct;
|
|||
void io_bitmap_share(struct task_struct *tsk);
|
||||
void io_bitmap_exit(struct task_struct *tsk);
|
||||
|
||||
static inline void native_tss_invalidate_io_bitmap(void)
|
||||
{
|
||||
/*
|
||||
* Invalidate the I/O bitmap by moving io_bitmap_base outside the
|
||||
* TSS limit so any subsequent I/O access from user space will
|
||||
* trigger a #GP.
|
||||
*
|
||||
* This is correct even when VMEXIT rewrites the TSS limit
|
||||
* to 0x67 as the only requirement is that the base points
|
||||
* outside the limit.
|
||||
*/
|
||||
this_cpu_write(cpu_tss_rw.x86_tss.io_bitmap_base,
|
||||
IO_BITMAP_OFFSET_INVALID);
|
||||
}
|
||||
|
||||
void native_tss_update_io_bitmap(void);
|
||||
|
||||
#ifdef CONFIG_PARAVIRT_XXL
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
#define tss_update_io_bitmap native_tss_update_io_bitmap
|
||||
#define tss_invalidate_io_bitmap native_tss_invalidate_io_bitmap
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -302,6 +302,11 @@ static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_X86_IOPL_IOPERM
|
||||
static inline void tss_invalidate_io_bitmap(void)
|
||||
{
|
||||
PVOP_VCALL0(cpu.invalidate_io_bitmap);
|
||||
}
|
||||
|
||||
static inline void tss_update_io_bitmap(void)
|
||||
{
|
||||
PVOP_VCALL0(cpu.update_io_bitmap);
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ struct pv_cpu_ops {
|
|||
void (*load_sp0)(unsigned long sp0);
|
||||
|
||||
#ifdef CONFIG_X86_IOPL_IOPERM
|
||||
void (*invalidate_io_bitmap)(void);
|
||||
void (*update_io_bitmap)(void);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -2316,12 +2316,12 @@ static int mp_irqdomain_create(int ioapic)
|
|||
ip->irqdomain = irq_domain_create_linear(fn, hwirqs, cfg->ops,
|
||||
(void *)(long)ioapic);
|
||||
|
||||
/* Release fw handle if it was allocated above */
|
||||
if (!cfg->dev)
|
||||
irq_domain_free_fwnode(fn);
|
||||
|
||||
if (!ip->irqdomain)
|
||||
if (!ip->irqdomain) {
|
||||
/* Release fw handle if it was allocated above */
|
||||
if (!cfg->dev)
|
||||
irq_domain_free_fwnode(fn);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ip->irqdomain->parent = parent;
|
||||
|
||||
|
|
|
|||
|
|
@ -263,12 +263,13 @@ void __init arch_init_msi_domain(struct irq_domain *parent)
|
|||
msi_default_domain =
|
||||
pci_msi_create_irq_domain(fn, &pci_msi_domain_info,
|
||||
parent);
|
||||
irq_domain_free_fwnode(fn);
|
||||
}
|
||||
if (!msi_default_domain)
|
||||
if (!msi_default_domain) {
|
||||
irq_domain_free_fwnode(fn);
|
||||
pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n");
|
||||
else
|
||||
} else {
|
||||
msi_default_domain->flags |= IRQ_DOMAIN_MSI_NOMASK_QUIRK;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IRQ_REMAP
|
||||
|
|
@ -301,7 +302,8 @@ struct irq_domain *arch_create_remap_msi_irq_domain(struct irq_domain *parent,
|
|||
if (!fn)
|
||||
return NULL;
|
||||
d = pci_msi_create_irq_domain(fn, &pci_msi_ir_domain_info, parent);
|
||||
irq_domain_free_fwnode(fn);
|
||||
if (!d)
|
||||
irq_domain_free_fwnode(fn);
|
||||
return d;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -364,7 +366,8 @@ static struct irq_domain *dmar_get_irq_domain(void)
|
|||
if (fn) {
|
||||
dmar_domain = msi_create_irq_domain(fn, &dmar_msi_domain_info,
|
||||
x86_vector_domain);
|
||||
irq_domain_free_fwnode(fn);
|
||||
if (!dmar_domain)
|
||||
irq_domain_free_fwnode(fn);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&dmar_lock);
|
||||
|
|
@ -489,7 +492,10 @@ struct irq_domain *hpet_create_irq_domain(int hpet_id)
|
|||
}
|
||||
|
||||
d = msi_create_irq_domain(fn, domain_info, parent);
|
||||
irq_domain_free_fwnode(fn);
|
||||
if (!d) {
|
||||
irq_domain_free_fwnode(fn);
|
||||
kfree(domain_info);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -446,12 +446,10 @@ static int x86_vector_activate(struct irq_domain *dom, struct irq_data *irqd,
|
|||
trace_vector_activate(irqd->irq, apicd->is_managed,
|
||||
apicd->can_reserve, reserve);
|
||||
|
||||
/* Nothing to do for fixed assigned vectors */
|
||||
if (!apicd->can_reserve && !apicd->is_managed)
|
||||
return 0;
|
||||
|
||||
raw_spin_lock_irqsave(&vector_lock, flags);
|
||||
if (reserve || irqd_is_managed_and_shutdown(irqd))
|
||||
if (!apicd->can_reserve && !apicd->is_managed)
|
||||
assign_irq_vector_any_locked(irqd);
|
||||
else if (reserve || irqd_is_managed_and_shutdown(irqd))
|
||||
vector_assign_managed_shutdown(irqd);
|
||||
else if (apicd->is_managed)
|
||||
ret = activate_managed(irqd);
|
||||
|
|
@ -709,7 +707,6 @@ int __init arch_early_irq_init(void)
|
|||
x86_vector_domain = irq_domain_create_tree(fn, &x86_vector_domain_ops,
|
||||
NULL);
|
||||
BUG_ON(x86_vector_domain == NULL);
|
||||
irq_domain_free_fwnode(fn);
|
||||
irq_set_default_host(x86_vector_domain);
|
||||
|
||||
arch_init_msi_domain(x86_vector_domain);
|
||||
|
|
@ -775,20 +772,10 @@ void lapic_offline(void)
|
|||
static int apic_set_affinity(struct irq_data *irqd,
|
||||
const struct cpumask *dest, bool force)
|
||||
{
|
||||
struct apic_chip_data *apicd = apic_chip_data(irqd);
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Core code can call here for inactive interrupts. For inactive
|
||||
* interrupts which use managed or reservation mode there is no
|
||||
* point in going through the vector assignment right now as the
|
||||
* activation will assign a vector which fits the destination
|
||||
* cpumask. Let the core code store the destination mask and be
|
||||
* done with it.
|
||||
*/
|
||||
if (!irqd_is_activated(irqd) &&
|
||||
(apicd->is_managed || apicd->can_reserve))
|
||||
return IRQ_SET_MASK_OK;
|
||||
if (WARN_ON_ONCE(!irqd_is_activated(irqd)))
|
||||
return -EIO;
|
||||
|
||||
raw_spin_lock(&vector_lock);
|
||||
cpumask_and(vector_searchmask, dest, cpu_online_mask);
|
||||
|
|
|
|||
|
|
@ -324,7 +324,8 @@ struct paravirt_patch_template pv_ops = {
|
|||
.cpu.swapgs = native_swapgs,
|
||||
|
||||
#ifdef CONFIG_X86_IOPL_IOPERM
|
||||
.cpu.update_io_bitmap = native_tss_update_io_bitmap,
|
||||
.cpu.invalidate_io_bitmap = native_tss_invalidate_io_bitmap,
|
||||
.cpu.update_io_bitmap = native_tss_update_io_bitmap,
|
||||
#endif
|
||||
|
||||
.cpu.start_context_switch = paravirt_nop,
|
||||
|
|
|
|||
|
|
@ -322,20 +322,6 @@ void arch_setup_new_exec(void)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_X86_IOPL_IOPERM
|
||||
static inline void tss_invalidate_io_bitmap(struct tss_struct *tss)
|
||||
{
|
||||
/*
|
||||
* Invalidate the I/O bitmap by moving io_bitmap_base outside the
|
||||
* TSS limit so any subsequent I/O access from user space will
|
||||
* trigger a #GP.
|
||||
*
|
||||
* This is correct even when VMEXIT rewrites the TSS limit
|
||||
* to 0x67 as the only requirement is that the base points
|
||||
* outside the limit.
|
||||
*/
|
||||
tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET_INVALID;
|
||||
}
|
||||
|
||||
static inline void switch_to_bitmap(unsigned long tifp)
|
||||
{
|
||||
/*
|
||||
|
|
@ -346,7 +332,7 @@ static inline void switch_to_bitmap(unsigned long tifp)
|
|||
* user mode.
|
||||
*/
|
||||
if (tifp & _TIF_IO_BITMAP)
|
||||
tss_invalidate_io_bitmap(this_cpu_ptr(&cpu_tss_rw));
|
||||
tss_invalidate_io_bitmap();
|
||||
}
|
||||
|
||||
static void tss_copy_io_bitmap(struct tss_struct *tss, struct io_bitmap *iobm)
|
||||
|
|
@ -380,7 +366,7 @@ void native_tss_update_io_bitmap(void)
|
|||
u16 *base = &tss->x86_tss.io_bitmap_base;
|
||||
|
||||
if (!test_thread_flag(TIF_IO_BITMAP)) {
|
||||
tss_invalidate_io_bitmap(tss);
|
||||
native_tss_invalidate_io_bitmap();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -303,6 +303,8 @@ DEFINE_IDTENTRY_ERRORCODE(exc_alignment_check)
|
|||
|
||||
do_trap(X86_TRAP_AC, SIGBUS, "alignment check", regs,
|
||||
error_code, BUS_ADRALN, NULL);
|
||||
|
||||
local_irq_disable();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ sqrt_stage_2_finish:
|
|||
|
||||
#ifdef PARANOID
|
||||
/* It should be possible to get here only if the arg is ffff....ffff */
|
||||
cmp $0xffffffff,FPU_fsqrt_arg_1
|
||||
cmpl $0xffffffff,FPU_fsqrt_arg_1
|
||||
jnz sqrt_stage_2_error
|
||||
#endif /* PARANOID */
|
||||
|
||||
|
|
|
|||
|
|
@ -167,9 +167,10 @@ static struct irq_domain *uv_get_irq_domain(void)
|
|||
goto out;
|
||||
|
||||
uv_domain = irq_domain_create_tree(fn, &uv_domain_ops, NULL);
|
||||
irq_domain_free_fwnode(fn);
|
||||
if (uv_domain)
|
||||
uv_domain->parent = x86_vector_domain;
|
||||
else
|
||||
irq_domain_free_fwnode(fn);
|
||||
out:
|
||||
mutex_unlock(&uv_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -870,6 +870,17 @@ static void xen_load_sp0(unsigned long sp0)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_X86_IOPL_IOPERM
|
||||
static void xen_invalidate_io_bitmap(void)
|
||||
{
|
||||
struct physdev_set_iobitmap iobitmap = {
|
||||
.bitmap = 0,
|
||||
.nr_ports = 0,
|
||||
};
|
||||
|
||||
native_tss_invalidate_io_bitmap();
|
||||
HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &iobitmap);
|
||||
}
|
||||
|
||||
static void xen_update_io_bitmap(void)
|
||||
{
|
||||
struct physdev_set_iobitmap iobitmap;
|
||||
|
|
@ -1099,6 +1110,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
|
|||
.load_sp0 = xen_load_sp0,
|
||||
|
||||
#ifdef CONFIG_X86_IOPL_IOPERM
|
||||
.invalidate_io_bitmap = xen_invalidate_io_bitmap,
|
||||
.update_io_bitmap = xen_update_io_bitmap,
|
||||
#endif
|
||||
.io_delay = xen_io_delay,
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ static int software_key_query(const struct kernel_pkey_params *params,
|
|||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
|
||||
ret = -ENOMEM;
|
||||
key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
|
||||
GFP_KERNEL);
|
||||
if (!key)
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ extern char *make_class_name(const char *name, struct kobject *kobj);
|
|||
extern int devres_release_all(struct device *dev);
|
||||
extern void device_block_probing(void);
|
||||
extern void device_unblock_probing(void);
|
||||
extern void driver_deferred_probe_force_trigger(void);
|
||||
|
||||
/* /sys/devices directory */
|
||||
extern struct kset *devices_kset;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ static DEFINE_MUTEX(wfs_lock);
|
|||
static LIST_HEAD(deferred_sync);
|
||||
static unsigned int defer_sync_state_count = 1;
|
||||
static unsigned int defer_fw_devlink_count;
|
||||
static LIST_HEAD(deferred_fw_devlink);
|
||||
static DEFINE_MUTEX(defer_fw_devlink_lock);
|
||||
static bool fw_devlink_is_permissive(void);
|
||||
|
||||
|
|
@ -754,11 +755,11 @@ static void __device_links_queue_sync_state(struct device *dev,
|
|||
*/
|
||||
dev->state_synced = true;
|
||||
|
||||
if (WARN_ON(!list_empty(&dev->links.defer_sync)))
|
||||
if (WARN_ON(!list_empty(&dev->links.defer_hook)))
|
||||
return;
|
||||
|
||||
get_device(dev);
|
||||
list_add_tail(&dev->links.defer_sync, list);
|
||||
list_add_tail(&dev->links.defer_hook, list);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -776,8 +777,8 @@ static void device_links_flush_sync_list(struct list_head *list,
|
|||
{
|
||||
struct device *dev, *tmp;
|
||||
|
||||
list_for_each_entry_safe(dev, tmp, list, links.defer_sync) {
|
||||
list_del_init(&dev->links.defer_sync);
|
||||
list_for_each_entry_safe(dev, tmp, list, links.defer_hook) {
|
||||
list_del_init(&dev->links.defer_hook);
|
||||
|
||||
if (dev != dont_lock_dev)
|
||||
device_lock(dev);
|
||||
|
|
@ -815,12 +816,12 @@ void device_links_supplier_sync_state_resume(void)
|
|||
if (defer_sync_state_count)
|
||||
goto out;
|
||||
|
||||
list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_sync) {
|
||||
list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_hook) {
|
||||
/*
|
||||
* Delete from deferred_sync list before queuing it to
|
||||
* sync_list because defer_sync is used for both lists.
|
||||
* sync_list because defer_hook is used for both lists.
|
||||
*/
|
||||
list_del_init(&dev->links.defer_sync);
|
||||
list_del_init(&dev->links.defer_hook);
|
||||
__device_links_queue_sync_state(dev, &sync_list);
|
||||
}
|
||||
out:
|
||||
|
|
@ -838,8 +839,8 @@ late_initcall(sync_state_resume_initcall);
|
|||
|
||||
static void __device_links_supplier_defer_sync(struct device *sup)
|
||||
{
|
||||
if (list_empty(&sup->links.defer_sync) && dev_has_sync_state(sup))
|
||||
list_add_tail(&sup->links.defer_sync, &deferred_sync);
|
||||
if (list_empty(&sup->links.defer_hook) && dev_has_sync_state(sup))
|
||||
list_add_tail(&sup->links.defer_hook, &deferred_sync);
|
||||
}
|
||||
|
||||
static void device_link_drop_managed(struct device_link *link)
|
||||
|
|
@ -1052,7 +1053,7 @@ void device_links_driver_cleanup(struct device *dev)
|
|||
WRITE_ONCE(link->status, DL_STATE_DORMANT);
|
||||
}
|
||||
|
||||
list_del_init(&dev->links.defer_sync);
|
||||
list_del_init(&dev->links.defer_hook);
|
||||
__device_links_no_driver(dev);
|
||||
|
||||
device_links_write_unlock();
|
||||
|
|
@ -1244,6 +1245,12 @@ static void fw_devlink_link_device(struct device *dev)
|
|||
fw_ret = -EAGAIN;
|
||||
} else {
|
||||
fw_ret = -ENODEV;
|
||||
/*
|
||||
* defer_hook is not used to add device to deferred_sync list
|
||||
* until device is bound. Since deferred fw devlink also blocks
|
||||
* probing, same list hook can be used for deferred_fw_devlink.
|
||||
*/
|
||||
list_add_tail(&dev->links.defer_hook, &deferred_fw_devlink);
|
||||
}
|
||||
|
||||
if (fw_ret == -ENODEV)
|
||||
|
|
@ -1312,6 +1319,9 @@ void fw_devlink_pause(void)
|
|||
*/
|
||||
void fw_devlink_resume(void)
|
||||
{
|
||||
struct device *dev, *tmp;
|
||||
LIST_HEAD(probe_list);
|
||||
|
||||
mutex_lock(&defer_fw_devlink_lock);
|
||||
if (!defer_fw_devlink_count) {
|
||||
WARN(true, "Unmatched fw_devlink pause/resume!");
|
||||
|
|
@ -1323,9 +1333,19 @@ void fw_devlink_resume(void)
|
|||
goto out;
|
||||
|
||||
device_link_add_missing_supplier_links();
|
||||
driver_deferred_probe_force_trigger();
|
||||
list_splice_tail_init(&deferred_fw_devlink, &probe_list);
|
||||
out:
|
||||
mutex_unlock(&defer_fw_devlink_lock);
|
||||
|
||||
/*
|
||||
* bus_probe_device() can cause new devices to get added and they'll
|
||||
* try to grab defer_fw_devlink_lock. So, this needs to be done outside
|
||||
* the defer_fw_devlink_lock.
|
||||
*/
|
||||
list_for_each_entry_safe(dev, tmp, &probe_list, links.defer_hook) {
|
||||
list_del_init(&dev->links.defer_hook);
|
||||
bus_probe_device(dev);
|
||||
}
|
||||
}
|
||||
/* Device links support end. */
|
||||
|
||||
|
|
@ -2172,7 +2192,7 @@ void device_initialize(struct device *dev)
|
|||
INIT_LIST_HEAD(&dev->links.consumers);
|
||||
INIT_LIST_HEAD(&dev->links.suppliers);
|
||||
INIT_LIST_HEAD(&dev->links.needs_suppliers);
|
||||
INIT_LIST_HEAD(&dev->links.defer_sync);
|
||||
INIT_LIST_HEAD(&dev->links.defer_hook);
|
||||
dev->links.status = DL_DEV_NO_DRIVER;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_initialize);
|
||||
|
|
|
|||
|
|
@ -164,11 +164,6 @@ static void driver_deferred_probe_trigger(void)
|
|||
if (!driver_deferred_probe_enable)
|
||||
return;
|
||||
|
||||
driver_deferred_probe_force_trigger();
|
||||
}
|
||||
|
||||
void driver_deferred_probe_force_trigger(void)
|
||||
{
|
||||
/*
|
||||
* A successful probe means that all the devices in the pending list
|
||||
* should be triggered to be reprobed. Move all the deferred devices
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
# subsystems should select the appropriate symbols.
|
||||
|
||||
config REGMAP
|
||||
default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SCCB || REGMAP_I3C)
|
||||
default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SCCB || REGMAP_I3C)
|
||||
select IRQ_DOMAIN if REGMAP_IRQ
|
||||
bool
|
||||
|
||||
|
|
|
|||
|
|
@ -463,29 +463,31 @@ static ssize_t regmap_cache_only_write_file(struct file *file,
|
|||
{
|
||||
struct regmap *map = container_of(file->private_data,
|
||||
struct regmap, cache_only);
|
||||
ssize_t result;
|
||||
bool was_enabled, require_sync = false;
|
||||
bool new_val, require_sync = false;
|
||||
int err;
|
||||
|
||||
err = kstrtobool_from_user(user_buf, count, &new_val);
|
||||
/* Ignore malforned data like debugfs_write_file_bool() */
|
||||
if (err)
|
||||
return count;
|
||||
|
||||
err = debugfs_file_get(file->f_path.dentry);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
|
||||
was_enabled = map->cache_only;
|
||||
|
||||
result = debugfs_write_file_bool(file, user_buf, count, ppos);
|
||||
if (result < 0) {
|
||||
map->unlock(map->lock_arg);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (map->cache_only && !was_enabled) {
|
||||
if (new_val && !map->cache_only) {
|
||||
dev_warn(map->dev, "debugfs cache_only=Y forced\n");
|
||||
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||
} else if (!map->cache_only && was_enabled) {
|
||||
} else if (!new_val && map->cache_only) {
|
||||
dev_warn(map->dev, "debugfs cache_only=N forced: syncing cache\n");
|
||||
require_sync = true;
|
||||
}
|
||||
map->cache_only = new_val;
|
||||
|
||||
map->unlock(map->lock_arg);
|
||||
debugfs_file_put(file->f_path.dentry);
|
||||
|
||||
if (require_sync) {
|
||||
err = regcache_sync(map);
|
||||
|
|
@ -493,7 +495,7 @@ static ssize_t regmap_cache_only_write_file(struct file *file,
|
|||
dev_err(map->dev, "Failed to sync cache %d\n", err);
|
||||
}
|
||||
|
||||
return result;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations regmap_cache_only_fops = {
|
||||
|
|
@ -508,28 +510,32 @@ static ssize_t regmap_cache_bypass_write_file(struct file *file,
|
|||
{
|
||||
struct regmap *map = container_of(file->private_data,
|
||||
struct regmap, cache_bypass);
|
||||
ssize_t result;
|
||||
bool was_enabled;
|
||||
bool new_val;
|
||||
int err;
|
||||
|
||||
err = kstrtobool_from_user(user_buf, count, &new_val);
|
||||
/* Ignore malforned data like debugfs_write_file_bool() */
|
||||
if (err)
|
||||
return count;
|
||||
|
||||
err = debugfs_file_get(file->f_path.dentry);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
|
||||
was_enabled = map->cache_bypass;
|
||||
|
||||
result = debugfs_write_file_bool(file, user_buf, count, ppos);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
if (map->cache_bypass && !was_enabled) {
|
||||
if (new_val && !map->cache_bypass) {
|
||||
dev_warn(map->dev, "debugfs cache_bypass=Y forced\n");
|
||||
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||
} else if (!map->cache_bypass && was_enabled) {
|
||||
} else if (!new_val && map->cache_bypass) {
|
||||
dev_warn(map->dev, "debugfs cache_bypass=N forced\n");
|
||||
}
|
||||
map->cache_bypass = new_val;
|
||||
|
||||
out:
|
||||
map->unlock(map->lock_arg);
|
||||
debugfs_file_put(file->f_path.dentry);
|
||||
|
||||
return result;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations regmap_cache_bypass_fops = {
|
||||
|
|
|
|||
|
|
@ -1364,7 +1364,7 @@ static int dev_get_regmap_match(struct device *dev, void *res, void *data)
|
|||
|
||||
/* If the user didn't specify a name match any */
|
||||
if (data)
|
||||
return (*r)->name == data;
|
||||
return !strcmp((*r)->name, data);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2021,7 +2021,8 @@ static ssize_t hot_add_show(struct class *class,
|
|||
return ret;
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
|
||||
}
|
||||
static CLASS_ATTR_RO(hot_add);
|
||||
static struct class_attribute class_attr_hot_add =
|
||||
__ATTR(hot_add, 0400, hot_add_show, NULL);
|
||||
|
||||
static ssize_t hot_remove_store(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
|
|
|
|||
|
|
@ -236,15 +236,14 @@ static int sysc_wait_softreset(struct sysc *ddata)
|
|||
syss_done = ddata->cfg.syss_mask;
|
||||
|
||||
if (syss_offset >= 0) {
|
||||
error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval,
|
||||
(rstval & ddata->cfg.syss_mask) ==
|
||||
syss_done,
|
||||
100, MAX_MODULE_SOFTRESET_WAIT);
|
||||
error = readx_poll_timeout_atomic(sysc_read_sysstatus, ddata,
|
||||
rstval, (rstval & ddata->cfg.syss_mask) ==
|
||||
syss_done, 100, MAX_MODULE_SOFTRESET_WAIT);
|
||||
|
||||
} else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
|
||||
error = readx_poll_timeout(sysc_read_sysconfig, ddata, rstval,
|
||||
!(rstval & sysc_mask),
|
||||
100, MAX_MODULE_SOFTRESET_WAIT);
|
||||
error = readx_poll_timeout_atomic(sysc_read_sysconfig, ddata,
|
||||
rstval, !(rstval & sysc_mask),
|
||||
100, MAX_MODULE_SOFTRESET_WAIT);
|
||||
}
|
||||
|
||||
return error;
|
||||
|
|
@ -1279,7 +1278,8 @@ static int __maybe_unused sysc_noirq_suspend(struct device *dev)
|
|||
|
||||
ddata = dev_get_drvdata(dev);
|
||||
|
||||
if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
|
||||
if (ddata->cfg.quirks &
|
||||
(SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
|
||||
return 0;
|
||||
|
||||
return pm_runtime_force_suspend(dev);
|
||||
|
|
@ -1291,7 +1291,8 @@ static int __maybe_unused sysc_noirq_resume(struct device *dev)
|
|||
|
||||
ddata = dev_get_drvdata(dev);
|
||||
|
||||
if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
|
||||
if (ddata->cfg.quirks &
|
||||
(SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
|
||||
return 0;
|
||||
|
||||
return pm_runtime_force_resume(dev);
|
||||
|
|
@ -1728,8 +1729,8 @@ static void sysc_quirk_rtc(struct sysc *ddata, bool lock)
|
|||
|
||||
local_irq_save(flags);
|
||||
/* RTC_STATUS BUSY bit may stay active for 1/32768 seconds (~30 usec) */
|
||||
error = readl_poll_timeout(ddata->module_va + 0x44, val,
|
||||
!(val & BIT(0)), 100, 50);
|
||||
error = readl_poll_timeout_atomic(ddata->module_va + 0x44, val,
|
||||
!(val & BIT(0)), 100, 50);
|
||||
if (error)
|
||||
dev_warn(ddata->dev, "rtc busy timeout\n");
|
||||
/* Now we have ~15 microseconds to read/write various registers */
|
||||
|
|
|
|||
|
|
@ -2116,6 +2116,7 @@ static struct virtio_device_id id_table[] = {
|
|||
{ VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID },
|
||||
{ 0 },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(virtio, id_table);
|
||||
|
||||
static unsigned int features[] = {
|
||||
VIRTIO_CONSOLE_F_SIZE,
|
||||
|
|
@ -2128,6 +2129,7 @@ static struct virtio_device_id rproc_serial_id_table[] = {
|
|||
#endif
|
||||
{ 0 },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(virtio, rproc_serial_id_table);
|
||||
|
||||
static unsigned int rproc_serial_features[] = {
|
||||
};
|
||||
|
|
@ -2280,6 +2282,5 @@ static void __exit fini(void)
|
|||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_DEVICE_TABLE(virtio, id_table);
|
||||
MODULE_DESCRIPTION("Virtio console driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ source "drivers/clk/versatile/Kconfig"
|
|||
config CLK_HSDK
|
||||
bool "PLL Driver for HSDK platform"
|
||||
depends on OF || COMPILE_TEST
|
||||
depends on IOMEM
|
||||
help
|
||||
This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs
|
||||
control.
|
||||
|
|
|
|||
|
|
@ -131,6 +131,18 @@ static const struct clk_div_table ast2600_eclk_div_table[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct clk_div_table ast2600_emmc_extclk_div_table[] = {
|
||||
{ 0x0, 2 },
|
||||
{ 0x1, 4 },
|
||||
{ 0x2, 6 },
|
||||
{ 0x3, 8 },
|
||||
{ 0x4, 10 },
|
||||
{ 0x5, 12 },
|
||||
{ 0x6, 14 },
|
||||
{ 0x7, 16 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct clk_div_table ast2600_mac_div_table[] = {
|
||||
{ 0x0, 4 },
|
||||
{ 0x1, 4 },
|
||||
|
|
@ -390,6 +402,11 @@ static struct clk_hw *aspeed_g6_clk_hw_register_gate(struct device *dev,
|
|||
return hw;
|
||||
}
|
||||
|
||||
static const char *const emmc_extclk_parent_names[] = {
|
||||
"emmc_extclk_hpll_in",
|
||||
"mpll",
|
||||
};
|
||||
|
||||
static const char * const vclk_parent_names[] = {
|
||||
"dpll",
|
||||
"d1pll",
|
||||
|
|
@ -459,16 +476,32 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(hw);
|
||||
aspeed_g6_clk_data->hws[ASPEED_CLK_UARTX] = hw;
|
||||
|
||||
/* EMMC ext clock divider */
|
||||
hw = clk_hw_register_gate(dev, "emmc_extclk_gate", "hpll", 0,
|
||||
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 15, 0,
|
||||
&aspeed_g6_clk_lock);
|
||||
/* EMMC ext clock */
|
||||
hw = clk_hw_register_fixed_factor(dev, "emmc_extclk_hpll_in", "hpll",
|
||||
0, 1, 2);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
hw = clk_hw_register_divider_table(dev, "emmc_extclk", "emmc_extclk_gate", 0,
|
||||
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 12, 3, 0,
|
||||
ast2600_div_table,
|
||||
&aspeed_g6_clk_lock);
|
||||
|
||||
hw = clk_hw_register_mux(dev, "emmc_extclk_mux",
|
||||
emmc_extclk_parent_names,
|
||||
ARRAY_SIZE(emmc_extclk_parent_names), 0,
|
||||
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 11, 1,
|
||||
0, &aspeed_g6_clk_lock);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
hw = clk_hw_register_gate(dev, "emmc_extclk_gate", "emmc_extclk_mux",
|
||||
0, scu_g6_base + ASPEED_G6_CLK_SELECTION1,
|
||||
15, 0, &aspeed_g6_clk_lock);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
hw = clk_hw_register_divider_table(dev, "emmc_extclk",
|
||||
"emmc_extclk_gate", 0,
|
||||
scu_g6_base +
|
||||
ASPEED_G6_CLK_SELECTION1, 12,
|
||||
3, 0, ast2600_emmc_extclk_div_table,
|
||||
&aspeed_g6_clk_lock);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
aspeed_g6_clk_data->hws[ASPEED_CLK_EMMC] = hw;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ config ARMADA_AP806_SYSCON
|
|||
|
||||
config ARMADA_AP_CPU_CLK
|
||||
bool
|
||||
select ARMADA_AP_CP_HELPER
|
||||
|
||||
config ARMADA_CP110_SYSCON
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -1274,18 +1274,26 @@ static ssize_t quad8_signal_cable_fault_read(struct counter_device *counter,
|
|||
struct counter_signal *signal,
|
||||
void *private, char *buf)
|
||||
{
|
||||
const struct quad8_iio *const priv = counter->priv;
|
||||
struct quad8_iio *const priv = counter->priv;
|
||||
const size_t channel_id = signal->id / 2;
|
||||
const bool disabled = !(priv->cable_fault_enable & BIT(channel_id));
|
||||
bool disabled;
|
||||
unsigned int status;
|
||||
unsigned int fault;
|
||||
|
||||
if (disabled)
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
disabled = !(priv->cable_fault_enable & BIT(channel_id));
|
||||
|
||||
if (disabled) {
|
||||
mutex_unlock(&priv->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Logic 0 = cable fault */
|
||||
status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
/* Mask respective channel and invert logic */
|
||||
fault = !(status & BIT(channel_id));
|
||||
|
||||
|
|
@ -1317,6 +1325,8 @@ static ssize_t quad8_signal_cable_fault_enable_write(
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
if (enable)
|
||||
priv->cable_fault_enable |= BIT(channel_id);
|
||||
else
|
||||
|
|
@ -1327,6 +1337,8 @@ static ssize_t quad8_signal_cable_fault_enable_write(
|
|||
|
||||
outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -1353,6 +1365,8 @@ static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
priv->fck_prescaler[channel_id] = prescaler;
|
||||
|
||||
/* Reset Byte Pointer */
|
||||
|
|
@ -1363,6 +1377,8 @@ static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
|
|||
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
|
||||
base_offset + 1);
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2464,7 +2464,7 @@ static struct cpufreq_driver intel_cpufreq = {
|
|||
.name = "intel_cpufreq",
|
||||
};
|
||||
|
||||
static struct cpufreq_driver *default_driver = &intel_pstate;
|
||||
static struct cpufreq_driver *default_driver;
|
||||
|
||||
static void intel_pstate_driver_cleanup(void)
|
||||
{
|
||||
|
|
@ -2758,6 +2758,7 @@ static int __init intel_pstate_init(void)
|
|||
hwp_active++;
|
||||
hwp_mode_bdw = id->driver_data;
|
||||
intel_pstate.attr = hwp_cpufreq_attrs;
|
||||
default_driver = &intel_pstate;
|
||||
goto hwp_cpu_matched;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -2775,7 +2776,8 @@ static int __init intel_pstate_init(void)
|
|||
return -ENODEV;
|
||||
}
|
||||
/* Without HWP start in the passive mode. */
|
||||
default_driver = &intel_cpufreq;
|
||||
if (!default_driver)
|
||||
default_driver = &intel_cpufreq;
|
||||
|
||||
hwp_cpu_matched:
|
||||
/*
|
||||
|
|
@ -2820,6 +2822,8 @@ static int __init intel_pstate_setup(char *str)
|
|||
|
||||
if (!strcmp(str, "disable")) {
|
||||
no_load = 1;
|
||||
} else if (!strcmp(str, "active")) {
|
||||
default_driver = &intel_pstate;
|
||||
} else if (!strcmp(str, "passive")) {
|
||||
default_driver = &intel_cpufreq;
|
||||
no_hwp = 1;
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
|
|||
size_t ret = 0;
|
||||
|
||||
dmabuf = dentry->d_fsdata;
|
||||
dma_resv_lock(dmabuf->resv, NULL);
|
||||
spin_lock(&dmabuf->name_lock);
|
||||
if (dmabuf->name)
|
||||
ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
|
||||
dma_resv_unlock(dmabuf->resv);
|
||||
spin_unlock(&dmabuf->name_lock);
|
||||
|
||||
return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
|
||||
dentry->d_name.name, ret > 0 ? name : "");
|
||||
|
|
@ -338,8 +338,10 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
|
|||
kfree(name);
|
||||
goto out_unlock;
|
||||
}
|
||||
spin_lock(&dmabuf->name_lock);
|
||||
kfree(dmabuf->name);
|
||||
dmabuf->name = name;
|
||||
spin_unlock(&dmabuf->name_lock);
|
||||
|
||||
out_unlock:
|
||||
dma_resv_unlock(dmabuf->resv);
|
||||
|
|
@ -402,10 +404,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
|
|||
/* Don't count the temporary reference taken inside procfs seq_show */
|
||||
seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
|
||||
seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
|
||||
dma_resv_lock(dmabuf->resv, NULL);
|
||||
spin_lock(&dmabuf->name_lock);
|
||||
if (dmabuf->name)
|
||||
seq_printf(m, "name:\t%s\n", dmabuf->name);
|
||||
dma_resv_unlock(dmabuf->resv);
|
||||
spin_unlock(&dmabuf->name_lock);
|
||||
}
|
||||
|
||||
static const struct file_operations dma_buf_fops = {
|
||||
|
|
@ -542,6 +544,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
|
|||
dmabuf->size = exp_info->size;
|
||||
dmabuf->exp_name = exp_info->exp_name;
|
||||
dmabuf->owner = exp_info->owner;
|
||||
spin_lock_init(&dmabuf->name_lock);
|
||||
init_waitqueue_head(&dmabuf->poll);
|
||||
dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
|
||||
dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
|
||||
|
|
|
|||
|
|
@ -1176,6 +1176,8 @@ static int dmatest_run_set(const char *val, const struct kernel_param *kp)
|
|||
} else if (dmatest_run) {
|
||||
if (!is_threaded_test_pending(info)) {
|
||||
pr_info("No channels configured, continue with any\n");
|
||||
if (!is_threaded_test_run(info))
|
||||
stop_threaded_test(info);
|
||||
add_threaded_test(info);
|
||||
}
|
||||
start_threaded_tests(info);
|
||||
|
|
|
|||
|
|
@ -118,16 +118,11 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
|
|||
{
|
||||
struct dw_dma *dw = to_dw_dma(dwc->chan.device);
|
||||
|
||||
if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags))
|
||||
return;
|
||||
|
||||
dw->initialize_chan(dwc);
|
||||
|
||||
/* Enable interrupts */
|
||||
channel_set_bit(dw, MASK.XFER, dwc->mask);
|
||||
channel_set_bit(dw, MASK.ERROR, dwc->mask);
|
||||
|
||||
set_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
@ -954,8 +949,6 @@ static void dwc_issue_pending(struct dma_chan *chan)
|
|||
|
||||
void do_dw_dma_off(struct dw_dma *dw)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
dma_writel(dw, CFG, 0);
|
||||
|
||||
channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
|
||||
|
|
@ -966,9 +959,6 @@ void do_dw_dma_off(struct dw_dma *dw)
|
|||
|
||||
while (dma_readl(dw, CFG) & DW_CFG_DMA_EN)
|
||||
cpu_relax();
|
||||
|
||||
for (i = 0; i < dw->dma.chancnt; i++)
|
||||
clear_bit(DW_DMA_IS_INITIALIZED, &dw->chan[i].flags);
|
||||
}
|
||||
|
||||
void do_dw_dma_on(struct dw_dma *dw)
|
||||
|
|
@ -1032,8 +1022,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
|
|||
/* Clear custom channel configuration */
|
||||
memset(&dwc->dws, 0, sizeof(struct dw_dma_slave));
|
||||
|
||||
clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
|
||||
|
||||
/* Disable interrupts */
|
||||
channel_clear_bit(dw, MASK.XFER, dwc->mask);
|
||||
channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
|
||||
|
|
|
|||
|
|
@ -352,26 +352,28 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
|
|||
/*
|
||||
* TCD parameters are stored in struct fsl_edma_hw_tcd in little
|
||||
* endian format. However, we need to load the TCD registers in
|
||||
* big- or little-endian obeying the eDMA engine model endian.
|
||||
* big- or little-endian obeying the eDMA engine model endian,
|
||||
* and this is performed from specific edma_write functions
|
||||
*/
|
||||
edma_writew(edma, 0, ®s->tcd[ch].csr);
|
||||
edma_writel(edma, le32_to_cpu(tcd->saddr), ®s->tcd[ch].saddr);
|
||||
edma_writel(edma, le32_to_cpu(tcd->daddr), ®s->tcd[ch].daddr);
|
||||
|
||||
edma_writew(edma, le16_to_cpu(tcd->attr), ®s->tcd[ch].attr);
|
||||
edma_writew(edma, le16_to_cpu(tcd->soff), ®s->tcd[ch].soff);
|
||||
edma_writel(edma, (s32)tcd->saddr, ®s->tcd[ch].saddr);
|
||||
edma_writel(edma, (s32)tcd->daddr, ®s->tcd[ch].daddr);
|
||||
|
||||
edma_writel(edma, le32_to_cpu(tcd->nbytes), ®s->tcd[ch].nbytes);
|
||||
edma_writel(edma, le32_to_cpu(tcd->slast), ®s->tcd[ch].slast);
|
||||
edma_writew(edma, (s16)tcd->attr, ®s->tcd[ch].attr);
|
||||
edma_writew(edma, tcd->soff, ®s->tcd[ch].soff);
|
||||
|
||||
edma_writew(edma, le16_to_cpu(tcd->citer), ®s->tcd[ch].citer);
|
||||
edma_writew(edma, le16_to_cpu(tcd->biter), ®s->tcd[ch].biter);
|
||||
edma_writew(edma, le16_to_cpu(tcd->doff), ®s->tcd[ch].doff);
|
||||
edma_writel(edma, (s32)tcd->nbytes, ®s->tcd[ch].nbytes);
|
||||
edma_writel(edma, (s32)tcd->slast, ®s->tcd[ch].slast);
|
||||
|
||||
edma_writel(edma, le32_to_cpu(tcd->dlast_sga),
|
||||
edma_writew(edma, (s16)tcd->citer, ®s->tcd[ch].citer);
|
||||
edma_writew(edma, (s16)tcd->biter, ®s->tcd[ch].biter);
|
||||
edma_writew(edma, (s16)tcd->doff, ®s->tcd[ch].doff);
|
||||
|
||||
edma_writel(edma, (s32)tcd->dlast_sga,
|
||||
®s->tcd[ch].dlast_sga);
|
||||
|
||||
edma_writew(edma, le16_to_cpu(tcd->csr), ®s->tcd[ch].csr);
|
||||
edma_writew(edma, (s16)tcd->csr, ®s->tcd[ch].csr);
|
||||
}
|
||||
|
||||
static inline
|
||||
|
|
@ -589,6 +591,8 @@ void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan)
|
|||
{
|
||||
struct virt_dma_desc *vdesc;
|
||||
|
||||
lockdep_assert_held(&fsl_chan->vchan.lock);
|
||||
|
||||
vdesc = vchan_next_desc(&fsl_chan->vchan);
|
||||
if (!vdesc)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#define EDMA_TCD_ATTR_DSIZE_16BIT BIT(0)
|
||||
#define EDMA_TCD_ATTR_DSIZE_32BIT BIT(1)
|
||||
#define EDMA_TCD_ATTR_DSIZE_64BIT (BIT(0) | BIT(1))
|
||||
#define EDMA_TCD_ATTR_DSIZE_32BYTE (BIT(3) | BIT(0))
|
||||
#define EDMA_TCD_ATTR_DSIZE_32BYTE (BIT(2) | BIT(0))
|
||||
#define EDMA_TCD_ATTR_SSIZE_8BIT 0
|
||||
#define EDMA_TCD_ATTR_SSIZE_16BIT (EDMA_TCD_ATTR_DSIZE_16BIT << 8)
|
||||
#define EDMA_TCD_ATTR_SSIZE_32BIT (EDMA_TCD_ATTR_DSIZE_32BIT << 8)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,13 @@ static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
|
|||
fsl_chan = &fsl_edma->chans[ch];
|
||||
|
||||
spin_lock(&fsl_chan->vchan.lock);
|
||||
|
||||
if (!fsl_chan->edesc) {
|
||||
/* terminate_all called before */
|
||||
spin_unlock(&fsl_chan->vchan.lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fsl_chan->edesc->iscyclic) {
|
||||
list_del(&fsl_chan->edesc->vdesc.node);
|
||||
vchan_cookie_complete(&fsl_chan->edesc->vdesc);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
|
|||
struct idxd_device *idxd;
|
||||
struct idxd_wq *wq;
|
||||
struct device *dev;
|
||||
int rc = 0;
|
||||
|
||||
wq = inode_wq(inode);
|
||||
idxd = wq->idxd;
|
||||
|
|
@ -81,17 +82,27 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
|
|||
|
||||
dev_dbg(dev, "%s called: %d\n", __func__, idxd_wq_refcount(wq));
|
||||
|
||||
if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq))
|
||||
return -EBUSY;
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&wq->wq_lock);
|
||||
|
||||
if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq)) {
|
||||
rc = -EBUSY;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ctx->wq = wq;
|
||||
filp->private_data = ctx;
|
||||
idxd_wq_get(wq);
|
||||
mutex_unlock(&wq->wq_lock);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
mutex_unlock(&wq->wq_lock);
|
||||
kfree(ctx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int idxd_cdev_release(struct inode *node, struct file *filep)
|
||||
|
|
@ -105,7 +116,9 @@ static int idxd_cdev_release(struct inode *node, struct file *filep)
|
|||
filep->private_data = NULL;
|
||||
|
||||
kfree(ctx);
|
||||
mutex_lock(&wq->wq_lock);
|
||||
idxd_wq_put(wq);
|
||||
mutex_unlock(&wq->wq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -320,6 +320,31 @@ void idxd_wq_unmap_portal(struct idxd_wq *wq)
|
|||
devm_iounmap(dev, wq->dportal);
|
||||
}
|
||||
|
||||
void idxd_wq_disable_cleanup(struct idxd_wq *wq)
|
||||
{
|
||||
struct idxd_device *idxd = wq->idxd;
|
||||
struct device *dev = &idxd->pdev->dev;
|
||||
int i, wq_offset;
|
||||
|
||||
lockdep_assert_held(&idxd->dev_lock);
|
||||
memset(&wq->wqcfg, 0, sizeof(wq->wqcfg));
|
||||
wq->type = IDXD_WQT_NONE;
|
||||
wq->size = 0;
|
||||
wq->group = NULL;
|
||||
wq->threshold = 0;
|
||||
wq->priority = 0;
|
||||
clear_bit(WQ_FLAG_DEDICATED, &wq->flags);
|
||||
memset(wq->name, 0, WQ_NAME_SIZE);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32);
|
||||
iowrite32(0, idxd->reg_base + wq_offset);
|
||||
dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n",
|
||||
wq->id, i, wq_offset,
|
||||
ioread32(idxd->reg_base + wq_offset));
|
||||
}
|
||||
}
|
||||
|
||||
/* Device control bits */
|
||||
static inline bool idxd_is_enabled(struct idxd_device *idxd)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -290,6 +290,7 @@ int idxd_wq_enable(struct idxd_wq *wq);
|
|||
int idxd_wq_disable(struct idxd_wq *wq);
|
||||
int idxd_wq_map_portal(struct idxd_wq *wq);
|
||||
void idxd_wq_unmap_portal(struct idxd_wq *wq);
|
||||
void idxd_wq_disable_cleanup(struct idxd_wq *wq);
|
||||
|
||||
/* submission */
|
||||
int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc);
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
|
|||
|
||||
iowrite32(cause, idxd->reg_base + IDXD_INTCAUSE_OFFSET);
|
||||
if (!err)
|
||||
return IRQ_HANDLED;
|
||||
goto out;
|
||||
|
||||
gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET);
|
||||
if (gensts.state == IDXD_DEVICE_STATE_HALT) {
|
||||
|
|
@ -162,6 +162,7 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
|
|||
spin_unlock_bh(&idxd->dev_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
idxd_unmask_msix_vector(idxd, irq_entry->id);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,6 +315,11 @@ static int idxd_config_bus_remove(struct device *dev)
|
|||
idxd_unregister_dma_device(idxd);
|
||||
spin_lock_irqsave(&idxd->dev_lock, flags);
|
||||
rc = idxd_device_disable(idxd);
|
||||
for (i = 0; i < idxd->max_wqs; i++) {
|
||||
struct idxd_wq *wq = &idxd->wqs[i];
|
||||
|
||||
idxd_wq_disable_cleanup(wq);
|
||||
}
|
||||
spin_unlock_irqrestore(&idxd->dev_lock, flags);
|
||||
module_put(THIS_MODULE);
|
||||
if (rc < 0)
|
||||
|
|
|
|||
|
|
@ -1331,8 +1331,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
|
|||
|
||||
sdma_channel_synchronize(chan);
|
||||
|
||||
if (sdmac->event_id0 >= 0)
|
||||
sdma_event_disable(sdmac, sdmac->event_id0);
|
||||
sdma_event_disable(sdmac, sdmac->event_id0);
|
||||
if (sdmac->event_id1)
|
||||
sdma_event_disable(sdmac, sdmac->event_id1);
|
||||
|
||||
|
|
@ -1632,11 +1631,9 @@ static int sdma_config(struct dma_chan *chan,
|
|||
memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg));
|
||||
|
||||
/* Set ENBLn earlier to make sure dma request triggered after that */
|
||||
if (sdmac->event_id0 >= 0) {
|
||||
if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
|
||||
return -EINVAL;
|
||||
sdma_event_enable(sdmac, sdmac->event_id0);
|
||||
}
|
||||
if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
|
||||
return -EINVAL;
|
||||
sdma_event_enable(sdmac, sdmac->event_id0);
|
||||
|
||||
if (sdmac->event_id1) {
|
||||
if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,18 @@
|
|||
|
||||
#include "../dmaengine.h"
|
||||
|
||||
int completion_timeout = 200;
|
||||
module_param(completion_timeout, int, 0644);
|
||||
MODULE_PARM_DESC(completion_timeout,
|
||||
"set ioat completion timeout [msec] (default 200 [msec])");
|
||||
int idle_timeout = 2000;
|
||||
module_param(idle_timeout, int, 0644);
|
||||
MODULE_PARM_DESC(idle_timeout,
|
||||
"set ioat idel timeout [msec] (default 2000 [msec])");
|
||||
|
||||
#define IDLE_TIMEOUT msecs_to_jiffies(idle_timeout)
|
||||
#define COMPLETION_TIMEOUT msecs_to_jiffies(completion_timeout)
|
||||
|
||||
static char *chanerr_str[] = {
|
||||
"DMA Transfer Source Address Error",
|
||||
"DMA Transfer Destination Address Error",
|
||||
|
|
|
|||
|
|
@ -104,8 +104,6 @@ struct ioatdma_chan {
|
|||
#define IOAT_RUN 5
|
||||
#define IOAT_CHAN_ACTIVE 6
|
||||
struct timer_list timer;
|
||||
#define COMPLETION_TIMEOUT msecs_to_jiffies(100)
|
||||
#define IDLE_TIMEOUT msecs_to_jiffies(2000)
|
||||
#define RESET_DELAY msecs_to_jiffies(100)
|
||||
struct ioatdma_device *ioat_dma;
|
||||
dma_addr_t completion_dma;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,13 @@ static irqreturn_t mcf_edma_tx_handler(int irq, void *dev_id)
|
|||
mcf_chan = &mcf_edma->chans[ch];
|
||||
|
||||
spin_lock(&mcf_chan->vchan.lock);
|
||||
|
||||
if (!mcf_chan->edesc) {
|
||||
/* terminate_all called before */
|
||||
spin_unlock(&mcf_chan->vchan.lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mcf_chan->edesc->iscyclic) {
|
||||
list_del(&mcf_chan->edesc->vdesc.node);
|
||||
vchan_cookie_complete(&mcf_chan->edesc->vdesc);
|
||||
|
|
|
|||
|
|
@ -586,6 +586,8 @@ static void usb_dmac_isr_transfer_end(struct usb_dmac_chan *chan)
|
|||
desc->residue = usb_dmac_get_current_residue(chan, desc,
|
||||
desc->sg_index - 1);
|
||||
desc->done_cookie = desc->vd.tx.cookie;
|
||||
desc->vd.tx_result.result = DMA_TRANS_NOERROR;
|
||||
desc->vd.tx_result.residue = desc->residue;
|
||||
vchan_cookie_complete(&desc->vd);
|
||||
|
||||
/* Restart the next transfer if this driver has a next desc */
|
||||
|
|
|
|||
|
|
@ -658,6 +658,7 @@ static int tegra_adma_alloc_chan_resources(struct dma_chan *dc)
|
|||
|
||||
ret = pm_runtime_get_sync(tdc2dev(tdc));
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(tdc2dev(tdc));
|
||||
free_irq(tdc->irq, tdc);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -869,8 +870,10 @@ static int tegra_adma_probe(struct platform_device *pdev)
|
|||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = pm_runtime_get_sync(&pdev->dev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
goto rpm_disable;
|
||||
}
|
||||
|
||||
ret = tegra_adma_init(tdma);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ struct udma_dev *of_xudma_dev_get(struct device_node *np, const char *property)
|
|||
ud = platform_get_drvdata(pdev);
|
||||
if (!ud) {
|
||||
pr_debug("UDMA has not been probed\n");
|
||||
put_device(&pdev->dev);
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1753,7 +1753,8 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
|
|||
dev_err(ud->ddev.dev,
|
||||
"Descriptor pool allocation failed\n");
|
||||
uc->use_dma_pool = false;
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto err_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1773,16 +1774,18 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
|
|||
|
||||
ret = udma_get_chan_pair(uc);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_cleanup;
|
||||
|
||||
ret = udma_alloc_tx_resources(uc);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
udma_put_rchan(uc);
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
ret = udma_alloc_rx_resources(uc);
|
||||
if (ret) {
|
||||
udma_free_tx_resources(uc);
|
||||
return ret;
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
uc->config.src_thread = ud->psil_base + uc->tchan->id;
|
||||
|
|
@ -1800,10 +1803,8 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
|
|||
uc->id);
|
||||
|
||||
ret = udma_alloc_tx_resources(uc);
|
||||
if (ret) {
|
||||
uc->config.remote_thread_id = -1;
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto err_cleanup;
|
||||
|
||||
uc->config.src_thread = ud->psil_base + uc->tchan->id;
|
||||
uc->config.dst_thread = uc->config.remote_thread_id;
|
||||
|
|
@ -1820,10 +1821,8 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
|
|||
uc->id);
|
||||
|
||||
ret = udma_alloc_rx_resources(uc);
|
||||
if (ret) {
|
||||
uc->config.remote_thread_id = -1;
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto err_cleanup;
|
||||
|
||||
uc->config.src_thread = uc->config.remote_thread_id;
|
||||
uc->config.dst_thread = (ud->psil_base + uc->rchan->id) |
|
||||
|
|
@ -1838,7 +1837,9 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
|
|||
/* Can not happen */
|
||||
dev_err(uc->ud->dev, "%s: chan%d invalid direction (%u)\n",
|
||||
__func__, uc->id, uc->config.dir);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_cleanup;
|
||||
|
||||
}
|
||||
|
||||
/* check if the channel configuration was successful */
|
||||
|
|
@ -1847,7 +1848,7 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
|
|||
|
||||
if (udma_is_chan_running(uc)) {
|
||||
dev_warn(ud->dev, "chan%d: is running!\n", uc->id);
|
||||
udma_stop(uc);
|
||||
udma_reset_chan(uc, false);
|
||||
if (udma_is_chan_running(uc)) {
|
||||
dev_err(ud->dev, "chan%d: won't stop!\n", uc->id);
|
||||
ret = -EBUSY;
|
||||
|
|
@ -1906,8 +1907,6 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
|
|||
|
||||
udma_reset_rings(uc);
|
||||
|
||||
INIT_DELAYED_WORK_ONSTACK(&uc->tx_drain.work,
|
||||
udma_check_tx_completion);
|
||||
return 0;
|
||||
|
||||
err_irq_free:
|
||||
|
|
@ -1919,7 +1918,7 @@ static int udma_alloc_chan_resources(struct dma_chan *chan)
|
|||
err_res_free:
|
||||
udma_free_tx_resources(uc);
|
||||
udma_free_rx_resources(uc);
|
||||
|
||||
err_cleanup:
|
||||
udma_reset_uchan(uc);
|
||||
|
||||
if (uc->use_dma_pool) {
|
||||
|
|
@ -3019,7 +3018,6 @@ static void udma_free_chan_resources(struct dma_chan *chan)
|
|||
}
|
||||
|
||||
cancel_delayed_work_sync(&uc->tx_drain.work);
|
||||
destroy_delayed_work_on_stack(&uc->tx_drain.work);
|
||||
|
||||
if (uc->irq_num_ring > 0) {
|
||||
free_irq(uc->irq_num_ring, uc);
|
||||
|
|
@ -3593,7 +3591,7 @@ static int udma_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(navss_node, "ti,udma-atype", &ud->atype);
|
||||
ret = of_property_read_u32(dev->of_node, "ti,udma-atype", &ud->atype);
|
||||
if (!ret && ud->atype > 2) {
|
||||
dev_err(dev, "Invalid atype: %u\n", ud->atype);
|
||||
return -EINVAL;
|
||||
|
|
@ -3711,6 +3709,7 @@ static int udma_probe(struct platform_device *pdev)
|
|||
tasklet_init(&uc->vc.task, udma_vchan_complete,
|
||||
(unsigned long)&uc->vc);
|
||||
init_completion(&uc->teardown_completed);
|
||||
INIT_DELAYED_WORK(&uc->tx_drain.work, udma_check_tx_completion);
|
||||
}
|
||||
|
||||
ret = dma_async_device_register(&ud->ddev);
|
||||
|
|
|
|||
|
|
@ -35,13 +35,16 @@ efi_status_t check_platform_features(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* Relocatable kernels can fix up the misalignment with respect to
|
||||
* MIN_KIMG_ALIGN, so they only require a minimum alignment of EFI_KIMG_ALIGN
|
||||
* (which accounts for the alignment of statically allocated objects such as
|
||||
* the swapper stack.)
|
||||
* Although relocatable kernels can fix up the misalignment with respect to
|
||||
* MIN_KIMG_ALIGN, the resulting virtual text addresses are subtly out of
|
||||
* sync with those recorded in the vmlinux when kaslr is disabled but the
|
||||
* image required relocation anyway. Therefore retain 2M alignment unless
|
||||
* KASLR is in use.
|
||||
*/
|
||||
static const u64 min_kimg_align = IS_ENABLED(CONFIG_RELOCATABLE) ? EFI_KIMG_ALIGN
|
||||
: MIN_KIMG_ALIGN;
|
||||
static u64 min_kimg_align(void)
|
||||
{
|
||||
return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
|
||||
}
|
||||
|
||||
efi_status_t handle_kernel_image(unsigned long *image_addr,
|
||||
unsigned long *image_size,
|
||||
|
|
@ -74,21 +77,21 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
|
|||
|
||||
kernel_size = _edata - _text;
|
||||
kernel_memsize = kernel_size + (_end - _edata);
|
||||
*reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align;
|
||||
*reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align();
|
||||
|
||||
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
|
||||
/*
|
||||
* If KASLR is enabled, and we have some randomness available,
|
||||
* locate the kernel at a randomized offset in physical memory.
|
||||
*/
|
||||
status = efi_random_alloc(*reserve_size, min_kimg_align,
|
||||
status = efi_random_alloc(*reserve_size, min_kimg_align(),
|
||||
reserve_addr, phys_seed);
|
||||
} else {
|
||||
status = EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
if (IS_ALIGNED((u64)_text - TEXT_OFFSET, min_kimg_align)) {
|
||||
if (IS_ALIGNED((u64)_text - TEXT_OFFSET, min_kimg_align())) {
|
||||
/*
|
||||
* Just execute from wherever we were loaded by the
|
||||
* UEFI PE/COFF loader if the alignment is suitable.
|
||||
|
|
@ -99,7 +102,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
|
|||
}
|
||||
|
||||
status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
|
||||
ULONG_MAX, min_kimg_align);
|
||||
ULONG_MAX, min_kimg_align());
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to relocate kernel\n");
|
||||
|
|
@ -108,7 +111,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
|
|||
}
|
||||
}
|
||||
|
||||
*image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align;
|
||||
*image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align();
|
||||
memcpy((void *)*image_addr, _text, kernel_size);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#include "efistub.h"
|
||||
|
||||
bool efi_nochunk;
|
||||
bool efi_nokaslr;
|
||||
bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);
|
||||
bool efi_noinitrd;
|
||||
int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
|
||||
bool efi_novamap;
|
||||
|
|
|
|||
|
|
@ -1295,27 +1295,37 @@ static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched)
|
|||
static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_job *job;
|
||||
struct drm_sched_job *s_job;
|
||||
struct drm_sched_job *s_job, *tmp;
|
||||
uint32_t preempt_seq;
|
||||
struct dma_fence *fence, **ptr;
|
||||
struct amdgpu_fence_driver *drv = &ring->fence_drv;
|
||||
struct drm_gpu_scheduler *sched = &ring->sched;
|
||||
bool preempted = true;
|
||||
|
||||
if (ring->funcs->type != AMDGPU_RING_TYPE_GFX)
|
||||
return;
|
||||
|
||||
preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2));
|
||||
if (preempt_seq <= atomic_read(&drv->last_seq))
|
||||
return;
|
||||
if (preempt_seq <= atomic_read(&drv->last_seq)) {
|
||||
preempted = false;
|
||||
goto no_preempt;
|
||||
}
|
||||
|
||||
preempt_seq &= drv->num_fences_mask;
|
||||
ptr = &drv->fences[preempt_seq];
|
||||
fence = rcu_dereference_protected(*ptr, 1);
|
||||
|
||||
no_preempt:
|
||||
spin_lock(&sched->job_list_lock);
|
||||
list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
|
||||
list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
|
||||
if (dma_fence_is_signaled(&s_job->s_fence->finished)) {
|
||||
/* remove job from ring_mirror_list */
|
||||
list_del_init(&s_job->node);
|
||||
sched->ops->free_job(s_job);
|
||||
continue;
|
||||
}
|
||||
job = to_amdgpu_job(s_job);
|
||||
if (job->fence == fence)
|
||||
if (preempted && job->fence == fence)
|
||||
/* mark the job as preempted */
|
||||
job->preemption_status |= AMDGPU_IB_PREEMPTED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7513,12 +7513,17 @@ static int gfx_v10_0_ring_preempt_ib(struct amdgpu_ring *ring)
|
|||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq;
|
||||
struct amdgpu_ring *kiq_ring = &kiq->ring;
|
||||
unsigned long flags;
|
||||
|
||||
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
|
||||
return -EINVAL;
|
||||
|
||||
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size))
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
|
||||
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* assert preemption condition */
|
||||
amdgpu_ring_set_preempt_cond_exec(ring, false);
|
||||
|
|
@ -7529,6 +7534,8 @@ static int gfx_v10_0_ring_preempt_ib(struct amdgpu_ring *ring)
|
|||
++ring->trail_seq);
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
/* poll the trailing fence */
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (ring->trail_seq ==
|
||||
|
|
|
|||
|
|
@ -314,30 +314,20 @@ static uint64_t sdma_v5_0_ring_get_rptr(struct amdgpu_ring *ring)
|
|||
static uint64_t sdma_v5_0_ring_get_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
u64 *wptr = NULL;
|
||||
uint64_t local_wptr = 0;
|
||||
u64 wptr;
|
||||
|
||||
if (ring->use_doorbell) {
|
||||
/* XXX check if swapping is necessary on BE */
|
||||
wptr = ((u64 *)&adev->wb.wb[ring->wptr_offs]);
|
||||
DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", *wptr);
|
||||
*wptr = (*wptr) >> 2;
|
||||
DRM_DEBUG("wptr/doorbell after shift == 0x%016llx\n", *wptr);
|
||||
wptr = READ_ONCE(*((u64 *)&adev->wb.wb[ring->wptr_offs]));
|
||||
DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", wptr);
|
||||
} else {
|
||||
u32 lowbit, highbit;
|
||||
|
||||
wptr = &local_wptr;
|
||||
lowbit = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR)) >> 2;
|
||||
highbit = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI)) >> 2;
|
||||
|
||||
DRM_DEBUG("wptr [%i]high== 0x%08x low==0x%08x\n",
|
||||
ring->me, highbit, lowbit);
|
||||
*wptr = highbit;
|
||||
*wptr = (*wptr) << 32;
|
||||
*wptr |= lowbit;
|
||||
wptr = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI));
|
||||
wptr = wptr << 32;
|
||||
wptr |= RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR));
|
||||
DRM_DEBUG("wptr before shift [%i] wptr == 0x%016llx\n", ring->me, wptr);
|
||||
}
|
||||
|
||||
return *wptr;
|
||||
return wptr >> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -974,6 +974,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
/* Update the actual used number of crtc */
|
||||
adev->mode_info.num_crtc = adev->dm.display_indexes_num;
|
||||
|
||||
/* create fake encoders for MST */
|
||||
dm_dp_create_fake_mst_encoders(adev);
|
||||
|
||||
/* TODO: Add_display_info? */
|
||||
|
||||
/* TODO use dynamic cursor width */
|
||||
|
|
@ -997,6 +1000,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
|
||||
static void amdgpu_dm_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->dm.display_indexes_num; i++) {
|
||||
drm_encoder_cleanup(&adev->dm.mst_encoders[i].base);
|
||||
}
|
||||
|
||||
amdgpu_dm_audio_fini(adev);
|
||||
|
||||
amdgpu_dm_destroy_drm_device(&adev->dm);
|
||||
|
|
@ -2010,6 +2019,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
|
|||
struct amdgpu_display_manager *dm;
|
||||
struct drm_connector *conn_base;
|
||||
struct amdgpu_device *adev;
|
||||
struct dc_link *link = NULL;
|
||||
static const u8 pre_computed_values[] = {
|
||||
50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
|
||||
71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};
|
||||
|
|
@ -2017,6 +2027,10 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
|
|||
if (!aconnector || !aconnector->dc_link)
|
||||
return;
|
||||
|
||||
link = aconnector->dc_link;
|
||||
if (link->connector_signal != SIGNAL_TYPE_EDP)
|
||||
return;
|
||||
|
||||
conn_base = &aconnector->base;
|
||||
adev = conn_base->dev->dev_private;
|
||||
dm = &adev->dm;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@
|
|||
*/
|
||||
|
||||
#define AMDGPU_DM_MAX_DISPLAY_INDEX 31
|
||||
|
||||
#define AMDGPU_DM_MAX_CRTC 6
|
||||
|
||||
/*
|
||||
#include "include/amdgpu_dal_power_if.h"
|
||||
#include "amdgpu_dm_irq.h"
|
||||
|
|
@ -328,6 +331,13 @@ struct amdgpu_display_manager {
|
|||
* available in FW
|
||||
*/
|
||||
const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
|
||||
|
||||
/**
|
||||
* @mst_encoders:
|
||||
*
|
||||
* fake encoders used for DP MST.
|
||||
*/
|
||||
struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC];
|
||||
};
|
||||
|
||||
struct amdgpu_dm_connector {
|
||||
|
|
@ -356,7 +366,6 @@ struct amdgpu_dm_connector {
|
|||
struct amdgpu_dm_dp_aux dm_dp_aux;
|
||||
struct drm_dp_mst_port *port;
|
||||
struct amdgpu_dm_connector *mst_port;
|
||||
struct amdgpu_encoder *mst_encoder;
|
||||
struct drm_dp_aux *dsc_aux;
|
||||
|
||||
/* TODO see if we can merge with ddc_bus or make a dm_connector */
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
|
|||
{
|
||||
struct amdgpu_dm_connector *aconnector =
|
||||
to_amdgpu_dm_connector(connector);
|
||||
struct amdgpu_encoder *amdgpu_encoder = aconnector->mst_encoder;
|
||||
|
||||
if (aconnector->dc_sink) {
|
||||
dc_link_remove_remote_sink(aconnector->dc_link,
|
||||
|
|
@ -105,8 +104,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
|
|||
|
||||
kfree(aconnector->edid);
|
||||
|
||||
drm_encoder_cleanup(&amdgpu_encoder->base);
|
||||
kfree(amdgpu_encoder);
|
||||
drm_connector_cleanup(connector);
|
||||
drm_dp_mst_put_port_malloc(aconnector->port);
|
||||
kfree(aconnector);
|
||||
|
|
@ -243,7 +240,11 @@ static struct drm_encoder *
|
|||
dm_mst_atomic_best_encoder(struct drm_connector *connector,
|
||||
struct drm_connector_state *connector_state)
|
||||
{
|
||||
return &to_amdgpu_dm_connector(connector)->mst_encoder->base;
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(connector_state->crtc);
|
||||
|
||||
return &adev->dm.mst_encoders[acrtc->crtc_id].base;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -306,31 +307,27 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
|
|||
.destroy = amdgpu_dm_encoder_destroy,
|
||||
};
|
||||
|
||||
static struct amdgpu_encoder *
|
||||
dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector)
|
||||
void
|
||||
dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_encoder *amdgpu_encoder;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_device *dev = adev->ddev;
|
||||
int i;
|
||||
|
||||
amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
|
||||
if (!amdgpu_encoder)
|
||||
return NULL;
|
||||
for (i = 0; i < adev->dm.display_indexes_num; i++) {
|
||||
struct amdgpu_encoder *amdgpu_encoder = &adev->dm.mst_encoders[i];
|
||||
struct drm_encoder *encoder = &amdgpu_encoder->base;
|
||||
|
||||
encoder = &amdgpu_encoder->base;
|
||||
encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
|
||||
encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
|
||||
|
||||
drm_encoder_init(
|
||||
dev,
|
||||
&amdgpu_encoder->base,
|
||||
&amdgpu_dm_encoder_funcs,
|
||||
DRM_MODE_ENCODER_DPMST,
|
||||
NULL);
|
||||
drm_encoder_init(
|
||||
dev,
|
||||
&amdgpu_encoder->base,
|
||||
&amdgpu_dm_encoder_funcs,
|
||||
DRM_MODE_ENCODER_DPMST,
|
||||
NULL);
|
||||
|
||||
drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
|
||||
|
||||
return amdgpu_encoder;
|
||||
drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
|
||||
}
|
||||
}
|
||||
|
||||
static struct drm_connector *
|
||||
|
|
@ -343,6 +340,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
|||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_dm_connector *aconnector;
|
||||
struct drm_connector *connector;
|
||||
int i;
|
||||
|
||||
aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
|
||||
if (!aconnector)
|
||||
|
|
@ -369,9 +367,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
|||
master->dc_link,
|
||||
master->connector_id);
|
||||
|
||||
aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
|
||||
drm_connector_attach_encoder(&aconnector->base,
|
||||
&aconnector->mst_encoder->base);
|
||||
for (i = 0; i < adev->dm.display_indexes_num; i++) {
|
||||
drm_connector_attach_encoder(&aconnector->base,
|
||||
&adev->dm.mst_encoders[i].base);
|
||||
}
|
||||
|
||||
connector->max_bpc_property = master->base.max_bpc_property;
|
||||
if (connector->max_bpc_property)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
|
|||
struct amdgpu_dm_connector *aconnector,
|
||||
int link_index);
|
||||
|
||||
void
|
||||
dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
|
||||
struct dc_state *dc_state);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink)
|
|||
}
|
||||
}
|
||||
|
||||
static void dc_stream_construct(struct dc_stream_state *stream,
|
||||
static bool dc_stream_construct(struct dc_stream_state *stream,
|
||||
struct dc_sink *dc_sink_data)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
|
@ -118,11 +118,17 @@ static void dc_stream_construct(struct dc_stream_state *stream,
|
|||
update_stream_signal(stream, dc_sink_data);
|
||||
|
||||
stream->out_transfer_func = dc_create_transfer_func();
|
||||
if (stream->out_transfer_func == NULL) {
|
||||
dc_sink_release(dc_sink_data);
|
||||
return false;
|
||||
}
|
||||
stream->out_transfer_func->type = TF_TYPE_BYPASS;
|
||||
stream->out_transfer_func->ctx = stream->ctx;
|
||||
|
||||
stream->stream_id = stream->ctx->dc_stream_id_count;
|
||||
stream->ctx->dc_stream_id_count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dc_stream_destruct(struct dc_stream_state *stream)
|
||||
|
|
@ -164,13 +170,20 @@ struct dc_stream_state *dc_create_stream_for_sink(
|
|||
|
||||
stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL);
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
goto alloc_fail;
|
||||
|
||||
dc_stream_construct(stream, sink);
|
||||
if (dc_stream_construct(stream, sink) == false)
|
||||
goto construct_fail;
|
||||
|
||||
kref_init(&stream->refcount);
|
||||
|
||||
return stream;
|
||||
|
||||
construct_fail:
|
||||
kfree(stream);
|
||||
|
||||
alloc_fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
|
||||
|
|
|
|||
|
|
@ -689,7 +689,7 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
|
||||
ret = smu_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
|
||||
1 << workload_type,
|
||||
NULL);
|
||||
if (ret) {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user