Merge ca1aaf9937
("Merge tag 'arm-fixes-6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc") into android-mainline
Steps on the way to 6.1-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I9c78d6a6dfd5ae5cc63d7e7f0f0aaa31a9a1e907
This commit is contained in:
commit
31142e1843
@ -976,6 +976,29 @@ All cgroup core files are prefixed with "cgroup."
|
||||
killing cgroups is a process directed operation, i.e. it affects
|
||||
the whole thread-group.
|
||||
|
||||
cgroup.pressure
|
||||
A read-write single value file that allowed values are "0" and "1".
|
||||
The default is "1".
|
||||
|
||||
Writing "0" to the file will disable the cgroup PSI accounting.
|
||||
Writing "1" to the file will re-enable the cgroup PSI accounting.
|
||||
|
||||
This control attribute is not hierarchical, so disable or enable PSI
|
||||
accounting in a cgroup does not affect PSI accounting in descendants
|
||||
and doesn't need pass enablement via ancestors from root.
|
||||
|
||||
The reason this control attribute exists is that PSI accounts stalls for
|
||||
each cgroup separately and aggregates it at each level of the hierarchy.
|
||||
This may cause non-negligible overhead for some workloads when under
|
||||
deep level of the hierarchy, in which case this control attribute can
|
||||
be used to disable PSI accounting in the non-leaf cgroups.
|
||||
|
||||
irq.pressure
|
||||
A read-write nested-keyed file.
|
||||
|
||||
Shows pressure stall information for IRQ/SOFTIRQ. See
|
||||
:ref:`Documentation/accounting/psi.rst <psi>` for details.
|
||||
|
||||
Controllers
|
||||
===========
|
||||
|
||||
|
@ -76,6 +76,8 @@ stable kernels.
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Cortex-A55 | #1530923 | ARM64_ERRATUM_1530923 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Cortex-A55 | #2441007 | ARM64_ERRATUM_2441007 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Cortex-A57 | #832075 | ARM64_ERRATUM_832075 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Cortex-A57 | #852523 | N/A |
|
||||
|
@ -66,6 +66,11 @@ properties:
|
||||
- enum:
|
||||
- allwinner,sun20i-d1-plic
|
||||
- const: thead,c900-plic
|
||||
- items:
|
||||
- const: sifive,plic-1.0.0
|
||||
- const: riscv,plic0
|
||||
deprecated: true
|
||||
description: For the QEMU virt machine only
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -79,24 +79,27 @@ properties:
|
||||
the LED.
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
|
||||
enum:
|
||||
# LED will act as a back-light, controlled by the framebuffer system
|
||||
- backlight
|
||||
# LED will turn on (but for leds-gpio see "default-state" property in
|
||||
# Documentation/devicetree/bindings/leds/leds-gpio.yaml)
|
||||
- default-on
|
||||
# LED "double" flashes at a load average based rate
|
||||
- heartbeat
|
||||
# LED indicates disk activity
|
||||
- disk-activity
|
||||
# LED indicates IDE disk activity (deprecated), in new implementations
|
||||
# use "disk-activity"
|
||||
- ide-disk
|
||||
# LED flashes at a fixed, configurable rate
|
||||
- timer
|
||||
# LED alters the brightness for the specified duration with one software
|
||||
# timer (requires "led-pattern" property)
|
||||
- pattern
|
||||
oneOf:
|
||||
- enum:
|
||||
# LED will act as a back-light, controlled by the framebuffer system
|
||||
- backlight
|
||||
# LED will turn on (but for leds-gpio see "default-state" property in
|
||||
# Documentation/devicetree/bindings/leds/leds-gpio.yaml)
|
||||
- default-on
|
||||
# LED "double" flashes at a load average based rate
|
||||
- heartbeat
|
||||
# LED indicates disk activity
|
||||
- disk-activity
|
||||
# LED indicates IDE disk activity (deprecated), in new implementations
|
||||
# use "disk-activity"
|
||||
- ide-disk
|
||||
# LED flashes at a fixed, configurable rate
|
||||
- timer
|
||||
# LED alters the brightness for the specified duration with one software
|
||||
# timer (requires "led-pattern" property)
|
||||
- pattern
|
||||
# LED is triggered by SD/MMC activity
|
||||
- pattern: "^mmc[0-9]+$"
|
||||
|
||||
led-pattern:
|
||||
description: |
|
||||
|
@ -9,6 +9,7 @@ title: RISC-V bindings for 'cpus' DT nodes
|
||||
maintainers:
|
||||
- Paul Walmsley <paul.walmsley@sifive.com>
|
||||
- Palmer Dabbelt <palmer@sifive.com>
|
||||
- Conor Dooley <conor@kernel.org>
|
||||
|
||||
description: |
|
||||
This document uses some terminology common to the RISC-V community
|
||||
@ -79,9 +80,7 @@ properties:
|
||||
insensitive, letters in the riscv,isa string must be all
|
||||
lowercase to simplify parsing.
|
||||
$ref: "/schemas/types.yaml#/definitions/string"
|
||||
enum:
|
||||
- rv64imac
|
||||
- rv64imafdc
|
||||
pattern: ^rv(?:64|32)imaf?d?q?c?b?v?k?h?(?:_[hsxz](?:[a-z])+)*$
|
||||
|
||||
# RISC-V requires 'timebase-frequency' in /cpus, so disallow it here
|
||||
timebase-frequency: false
|
||||
|
@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
title: Microchip PolarFire SoC-based boards
|
||||
|
||||
maintainers:
|
||||
- Cyril Jean <Cyril.Jean@microchip.com>
|
||||
- Lewis Hanly <lewis.hanly@microchip.com>
|
||||
- Conor Dooley <conor.dooley@microchip.com>
|
||||
- Daire McNamara <daire.mcnamara@microchip.com>
|
||||
|
||||
description:
|
||||
Microchip PolarFire SoC-based boards
|
||||
@ -17,12 +17,20 @@ properties:
|
||||
$nodename:
|
||||
const: '/'
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- microchip,mpfs-icicle-kit
|
||||
- microchip,mpfs-icicle-reference-rtlv2203
|
||||
- sundance,polarberry
|
||||
- const: microchip,mpfs
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- microchip,mpfs-icicle-reference-rtlv2203
|
||||
- microchip,mpfs-icicle-reference-rtlv2210
|
||||
- const: microchip,mpfs-icicle-kit
|
||||
- const: microchip,mpfs
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- aries,m100pfsevp
|
||||
- microchip,mpfs-sev-kit
|
||||
- sundance,polarberry
|
||||
- const: microchip,mpfs
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
|
@ -2,18 +2,18 @@
|
||||
# Copyright (C) 2020 SiFive, Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/riscv/sifive-l2-cache.yaml#
|
||||
$id: http://devicetree.org/schemas/riscv/sifive,ccache0.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SiFive L2 Cache Controller
|
||||
title: SiFive Composable Cache Controller
|
||||
|
||||
maintainers:
|
||||
- Sagar Kadam <sagar.kadam@sifive.com>
|
||||
- Paul Walmsley <paul.walmsley@sifive.com>
|
||||
|
||||
description:
|
||||
The SiFive Level 2 Cache Controller is used to provide access to fast copies
|
||||
of memory for masters in a Core Complex. The Level 2 Cache Controller also
|
||||
The SiFive Composable Cache Controller is used to provide access to fast copies
|
||||
of memory for masters in a Core Complex. The Composable Cache Controller also
|
||||
acts as directory-based coherency manager.
|
||||
All the properties in ePAPR/DeviceTree specification applies for this platform.
|
||||
|
||||
@ -22,6 +22,7 @@ select:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- sifive,ccache0
|
||||
- sifive,fu540-c000-ccache
|
||||
- sifive,fu740-c000-ccache
|
||||
|
||||
@ -33,6 +34,7 @@ properties:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- sifive,ccache0
|
||||
- sifive,fu540-c000-ccache
|
||||
- sifive,fu740-c000-ccache
|
||||
- const: cache
|
||||
@ -45,7 +47,7 @@ properties:
|
||||
const: 64
|
||||
|
||||
cache-level:
|
||||
const: 2
|
||||
enum: [2, 3]
|
||||
|
||||
cache-sets:
|
||||
enum: [1024, 2048]
|
||||
@ -115,6 +117,22 @@ allOf:
|
||||
cache-sets:
|
||||
const: 1024
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: sifive,ccache0
|
||||
|
||||
then:
|
||||
properties:
|
||||
cache-level:
|
||||
enum: [2, 3]
|
||||
|
||||
else:
|
||||
properties:
|
||||
cache-level:
|
||||
const: 2
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
@ -22,12 +22,18 @@ description:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- sifive,fu540-c000-clint
|
||||
- starfive,jh7100-clint
|
||||
- canaan,k210-clint
|
||||
- const: sifive,clint0
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- sifive,fu540-c000-clint
|
||||
- starfive,jh7100-clint
|
||||
- canaan,k210-clint
|
||||
- const: sifive,clint0
|
||||
- items:
|
||||
- const: sifive,clint0
|
||||
- const: riscv,clint0
|
||||
deprecated: true
|
||||
description: For the QEMU virt machine only
|
||||
|
||||
description:
|
||||
Should be "<vendor>,<chip>-clint" and "sifive,clint<version>".
|
||||
|
@ -8,6 +8,7 @@ RISC-V architecture
|
||||
boot-image-header
|
||||
vm-layout
|
||||
patch-acceptance
|
||||
uabi
|
||||
|
||||
features
|
||||
|
||||
|
6
Documentation/riscv/uabi.rst
Normal file
6
Documentation/riscv/uabi.rst
Normal file
@ -0,0 +1,6 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
RISC-V Linux User ABI
|
||||
=====================
|
||||
|
||||
Misaligned accesses are supported in userspace, but they may perform poorly.
|
@ -752,7 +752,7 @@ ALIBABA PMU DRIVER
|
||||
M: Shuai Xue <xueshuai@linux.alibaba.com>
|
||||
S: Supported
|
||||
F: Documentation/admin-guide/perf/alibaba_pmu.rst
|
||||
F: drivers/perf/alibaba_uncore_dwr_pmu.c
|
||||
F: drivers/perf/alibaba_uncore_drw_pmu.c
|
||||
|
||||
ALIENWARE WMI DRIVER
|
||||
L: Dell.Client.Kernel@dell.com
|
||||
@ -17709,6 +17709,7 @@ M: Palmer Dabbelt <palmer@dabbelt.com>
|
||||
M: Albert Ou <aou@eecs.berkeley.edu>
|
||||
L: linux-riscv@lists.infradead.org
|
||||
S: Supported
|
||||
Q: https://patchwork.kernel.org/project/linux-riscv/list/
|
||||
P: Documentation/riscv/patch-acceptance.rst
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git
|
||||
F: arch/riscv/
|
||||
@ -17720,12 +17721,13 @@ M: Conor Dooley <conor.dooley@microchip.com>
|
||||
M: Daire McNamara <daire.mcnamara@microchip.com>
|
||||
L: linux-riscv@lists.infradead.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/clock/microchip,mpfs.yaml
|
||||
F: Documentation/devicetree/bindings/clock/microchip,mpfs*.yaml
|
||||
F: Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml
|
||||
F: Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml
|
||||
F: Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
|
||||
F: Documentation/devicetree/bindings/net/can/microchip,mpfs-can.yaml
|
||||
F: Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml
|
||||
F: Documentation/devicetree/bindings/riscv/microchip.yaml
|
||||
F: Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml
|
||||
F: Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml
|
||||
F: Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
|
||||
|
@ -238,7 +238,7 @@ void pxa_usb_phy_deinit(void __iomem *phy_reg)
|
||||
static u64 __maybe_unused usb_dma_mask = ~(u32)0;
|
||||
|
||||
#if IS_ENABLED(CONFIG_PHY_PXA_USB)
|
||||
struct resource pxa168_usb_phy_resources[] = {
|
||||
static struct resource pxa168_usb_phy_resources[] = {
|
||||
[0] = {
|
||||
.start = PXA168_U2O_PHYBASE,
|
||||
.end = PXA168_U2O_PHYBASE + USB_PHY_RANGE,
|
||||
@ -259,7 +259,7 @@ struct platform_device pxa168_device_usb_phy = {
|
||||
#endif /* CONFIG_PHY_PXA_USB */
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_MV_UDC)
|
||||
struct resource pxa168_u2o_resources[] = {
|
||||
static struct resource pxa168_u2o_resources[] = {
|
||||
/* regbase */
|
||||
[0] = {
|
||||
.start = PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
|
||||
@ -294,7 +294,7 @@ struct platform_device pxa168_device_u2o = {
|
||||
#endif /* CONFIG_USB_MV_UDC */
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_EHCI_MV_U2O)
|
||||
struct resource pxa168_u2oehci_resources[] = {
|
||||
static struct resource pxa168_u2oehci_resources[] = {
|
||||
[0] = {
|
||||
.start = PXA168_U2O_REGBASE,
|
||||
.end = PXA168_U2O_REGBASE + USB_REG_RANGE,
|
||||
@ -321,7 +321,7 @@ struct platform_device pxa168_device_u2oehci = {
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_MV_OTG)
|
||||
struct resource pxa168_u2ootg_resources[] = {
|
||||
static struct resource pxa168_u2ootg_resources[] = {
|
||||
/* regbase */
|
||||
[0] = {
|
||||
.start = PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
|
||||
|
@ -25,11 +25,8 @@ extern struct pl022_ssp_controller pl022_plat_data;
|
||||
extern struct pl08x_platform_data pl080_plat_data;
|
||||
|
||||
void __init spear_setup_of_timer(void);
|
||||
void __init spear3xx_clk_init(void __iomem *misc_base,
|
||||
void __iomem *soc_config_base);
|
||||
void __init spear3xx_map_io(void);
|
||||
void __init spear3xx_dt_init_irq(void);
|
||||
void __init spear6xx_clk_init(void __iomem *misc_base);
|
||||
void __init spear13xx_map_io(void);
|
||||
void __init spear13xx_l2x0_init(void);
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/amba/pl022.h>
|
||||
#include <linux/amba/pl080.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk/spear.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include "pl080.h"
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <linux/amba/pl08x.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk/spear.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
@ -339,7 +340,7 @@ static struct pl08x_platform_data spear6xx_pl080_plat_data = {
|
||||
* 0xD0000000 0xFD000000
|
||||
* 0xFC000000 0xFC000000
|
||||
*/
|
||||
struct map_desc spear6xx_io_desc[] __initdata = {
|
||||
static struct map_desc spear6xx_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = (unsigned long)VA_SPEAR6XX_ML_CPU_BASE,
|
||||
.pfn = __phys_to_pfn(SPEAR_ICM3_ML1_2_BASE),
|
||||
@ -359,12 +360,12 @@ struct map_desc spear6xx_io_desc[] __initdata = {
|
||||
};
|
||||
|
||||
/* This will create static memory mapping for selected devices */
|
||||
void __init spear6xx_map_io(void)
|
||||
static void __init spear6xx_map_io(void)
|
||||
{
|
||||
iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
|
||||
}
|
||||
|
||||
void __init spear6xx_timer_init(void)
|
||||
static void __init spear6xx_timer_init(void)
|
||||
{
|
||||
char pclk_name[] = "pll3_clk";
|
||||
struct clk *gpt_clk, *pclk;
|
||||
@ -394,7 +395,7 @@ void __init spear6xx_timer_init(void)
|
||||
}
|
||||
|
||||
/* Add auxdata to pass platform data */
|
||||
struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
|
||||
static struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
|
||||
&spear6xx_pl080_plat_data),
|
||||
{}
|
||||
|
@ -632,6 +632,23 @@ config ARM64_ERRATUM_1530923
|
||||
config ARM64_WORKAROUND_REPEAT_TLBI
|
||||
bool
|
||||
|
||||
config ARM64_ERRATUM_2441007
|
||||
bool "Cortex-A55: Completion of affected memory accesses might not be guaranteed by completion of a TLBI"
|
||||
default y
|
||||
select ARM64_WORKAROUND_REPEAT_TLBI
|
||||
help
|
||||
This option adds a workaround for ARM Cortex-A55 erratum #2441007.
|
||||
|
||||
Under very rare circumstances, affected Cortex-A55 CPUs
|
||||
may not handle a race between a break-before-make sequence on one
|
||||
CPU, and another CPU accessing the same page. This could allow a
|
||||
store to a page that has been unmapped.
|
||||
|
||||
Work around this by adding the affected CPUs to the list that needs
|
||||
TLB sequences to be done twice.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config ARM64_ERRATUM_1286807
|
||||
bool "Cortex-A76: Modification of the translation table for a virtual address might lead to read-after-read ordering violation"
|
||||
default y
|
||||
|
@ -60,6 +60,7 @@
|
||||
#define ARM_CPU_IMP_FUJITSU 0x46
|
||||
#define ARM_CPU_IMP_HISI 0x48
|
||||
#define ARM_CPU_IMP_APPLE 0x61
|
||||
#define ARM_CPU_IMP_AMPERE 0xC0
|
||||
|
||||
#define ARM_CPU_PART_AEM_V8 0xD0F
|
||||
#define ARM_CPU_PART_FOUNDATION 0xD00
|
||||
@ -123,6 +124,8 @@
|
||||
#define APPLE_CPU_PART_M1_ICESTORM_MAX 0x028
|
||||
#define APPLE_CPU_PART_M1_FIRESTORM_MAX 0x029
|
||||
|
||||
#define AMPERE_CPU_PART_AMPERE1 0xAC3
|
||||
|
||||
#define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
|
||||
#define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
|
||||
#define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
|
||||
@ -172,6 +175,7 @@
|
||||
#define MIDR_APPLE_M1_FIRESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO)
|
||||
#define MIDR_APPLE_M1_ICESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX)
|
||||
#define MIDR_APPLE_M1_FIRESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX)
|
||||
#define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1)
|
||||
|
||||
/* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
|
||||
#define MIDR_FUJITSU_ERRATUM_010001 MIDR_FUJITSU_A64FX
|
||||
|
@ -230,6 +230,11 @@ static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
|
||||
ERRATA_MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xe),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_2441007
|
||||
{
|
||||
ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_2441009
|
||||
{
|
||||
/* Cortex-A510 r0p0 -> r1p1. Fixed in r1p2 */
|
||||
|
@ -48,7 +48,12 @@ static void mte_sync_page_tags(struct page *page, pte_t old_pte,
|
||||
if (!pte_is_tagged)
|
||||
return;
|
||||
|
||||
mte_clear_page_tags(page_address(page));
|
||||
/*
|
||||
* Test PG_mte_tagged again in case it was racing with another
|
||||
* set_pte_at().
|
||||
*/
|
||||
if (!test_and_set_bit(PG_mte_tagged, &page->flags))
|
||||
mte_clear_page_tags(page_address(page));
|
||||
}
|
||||
|
||||
void mte_sync_tags(pte_t old_pte, pte_t pte)
|
||||
@ -64,7 +69,7 @@ void mte_sync_tags(pte_t old_pte, pte_t pte)
|
||||
|
||||
/* if PG_mte_tagged is set, tags have already been initialised */
|
||||
for (i = 0; i < nr_pages; i++, page++) {
|
||||
if (!test_and_set_bit(PG_mte_tagged, &page->flags))
|
||||
if (!test_bit(PG_mte_tagged, &page->flags))
|
||||
mte_sync_page_tags(page, old_pte, check_swap,
|
||||
pte_is_tagged);
|
||||
}
|
||||
|
@ -868,6 +868,10 @@ u8 spectre_bhb_loop_affected(int scope)
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k11_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_AMPERE1),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k8_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
|
||||
@ -878,6 +882,8 @@ u8 spectre_bhb_loop_affected(int scope)
|
||||
k = 32;
|
||||
else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list))
|
||||
k = 24;
|
||||
else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list))
|
||||
k = 11;
|
||||
else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list))
|
||||
k = 8;
|
||||
|
||||
|
@ -53,7 +53,12 @@ bool mte_restore_tags(swp_entry_t entry, struct page *page)
|
||||
if (!tags)
|
||||
return false;
|
||||
|
||||
mte_restore_page_tags(page_address(page), tags);
|
||||
/*
|
||||
* Test PG_mte_tagged again in case it was racing with another
|
||||
* set_pte_at().
|
||||
*/
|
||||
if (!test_and_set_bit(PG_mte_tagged, &page->flags))
|
||||
mte_restore_page_tags(page_address(page), tags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -732,7 +732,7 @@ EndSysreg
|
||||
|
||||
Sysreg SCTLR_EL1 3 0 1 0 0
|
||||
Field 63 TIDCP
|
||||
Field 62 SPINMASK
|
||||
Field 62 SPINTMASK
|
||||
Field 61 NMI
|
||||
Field 60 EnTP2
|
||||
Res0 59:58
|
||||
|
@ -412,6 +412,9 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
|
||||
__update_tlb(vma, address, ptep);
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_UPDATE_MMU_TLB
|
||||
#define update_mmu_tlb update_mmu_cache
|
||||
|
||||
static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
|
||||
unsigned long address, pmd_t *pmdp)
|
||||
{
|
||||
|
@ -22,10 +22,10 @@
|
||||
|
||||
struct alt_instr {
|
||||
s32 orig_offset; /* offset to original instructions */
|
||||
s32 len; /* end of original instructions */
|
||||
u32 cond; /* see ALT_COND_XXX */
|
||||
s16 len; /* end of original instructions */
|
||||
u16 cond; /* see ALT_COND_XXX */
|
||||
u32 replacement; /* replacement instruction or code */
|
||||
};
|
||||
} __packed;
|
||||
|
||||
void set_kernel_text_rw(int enable_read_write);
|
||||
void apply_alternatives_all(void);
|
||||
@ -35,8 +35,9 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
|
||||
/* Alternative SMP implementation. */
|
||||
#define ALTERNATIVE(cond, replacement) "!0:" \
|
||||
".section .altinstructions, \"aw\" !" \
|
||||
".word (0b-4-.), 1, " __stringify(cond) "," \
|
||||
__stringify(replacement) " !" \
|
||||
".word (0b-4-.) !" \
|
||||
".hword 1, " __stringify(cond) " !" \
|
||||
".word " __stringify(replacement) " !" \
|
||||
".previous"
|
||||
|
||||
#else
|
||||
@ -44,15 +45,17 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
|
||||
/* to replace one single instructions by a new instruction */
|
||||
#define ALTERNATIVE(from, to, cond, replacement)\
|
||||
.section .altinstructions, "aw" ! \
|
||||
.word (from - .), (to - from)/4 ! \
|
||||
.word cond, replacement ! \
|
||||
.word (from - .) ! \
|
||||
.hword (to - from)/4, cond ! \
|
||||
.word replacement ! \
|
||||
.previous
|
||||
|
||||
/* to replace multiple instructions by new code */
|
||||
#define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\
|
||||
.section .altinstructions, "aw" ! \
|
||||
.word (from - .), -num_instructions ! \
|
||||
.word cond, (new_instr_ptr - .) ! \
|
||||
.word (from - .) ! \
|
||||
.hword -num_instructions, cond ! \
|
||||
.word (new_instr_ptr - .) ! \
|
||||
.previous
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
@ -19,9 +19,6 @@ extern unsigned long parisc_pat_pdc_cap; /* PDC capabilities (PAT) */
|
||||
#define PDC_TYPE_SYSTEM_MAP 1 /* 32-bit, but supports PDC_SYSTEM_MAP */
|
||||
#define PDC_TYPE_SNAKE 2 /* Doesn't support SYSTEM_MAP */
|
||||
|
||||
void pdc_console_init(void); /* in pdc_console.c */
|
||||
void pdc_console_restart(void);
|
||||
|
||||
void setup_pdc(void); /* in inventory.c */
|
||||
|
||||
/* wrapper-functions from pdc.c */
|
||||
|
@ -192,6 +192,11 @@ extern void __update_cache(pte_t pte);
|
||||
#define _PAGE_PRESENT_BIT 22 /* (0x200) Software: translation valid */
|
||||
#define _PAGE_HPAGE_BIT 21 /* (0x400) Software: Huge Page */
|
||||
#define _PAGE_USER_BIT 20 /* (0x800) Software: User accessible page */
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
#define _PAGE_SPECIAL_BIT _PAGE_DMB_BIT /* DMB feature is currently unused */
|
||||
#else
|
||||
#define _PAGE_SPECIAL_BIT _PAGE_HPAGE_BIT /* use unused HUGE PAGE bit */
|
||||
#endif
|
||||
|
||||
/* N.B. The bits are defined in terms of a 32 bit word above, so the */
|
||||
/* following macro is ok for both 32 and 64 bit. */
|
||||
@ -219,7 +224,7 @@ extern void __update_cache(pte_t pte);
|
||||
#define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT))
|
||||
#define _PAGE_HUGE (1 << xlate_pabit(_PAGE_HPAGE_BIT))
|
||||
#define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT))
|
||||
#define _PAGE_SPECIAL (_PAGE_DMB)
|
||||
#define _PAGE_SPECIAL (1 << xlate_pabit(_PAGE_SPECIAL_BIT))
|
||||
|
||||
#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED)
|
||||
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_SPECIAL)
|
||||
|
@ -26,7 +26,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
|
||||
struct alt_instr *entry;
|
||||
int index = 0, applied = 0;
|
||||
int num_cpus = num_online_cpus();
|
||||
u32 cond_check;
|
||||
u16 cond_check;
|
||||
|
||||
cond_check = ALT_COND_ALWAYS |
|
||||
((num_cpus == 1) ? ALT_COND_NO_SMP : 0) |
|
||||
@ -45,8 +45,9 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
|
||||
|
||||
for (entry = start; entry < end; entry++, index++) {
|
||||
|
||||
u32 *from, cond, replacement;
|
||||
s32 len;
|
||||
u32 *from, replacement;
|
||||
u16 cond;
|
||||
s16 len;
|
||||
|
||||
from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset);
|
||||
len = entry->len;
|
||||
|
@ -499,6 +499,10 @@
|
||||
* Finally, _PAGE_READ goes in the top bit of PL1 (so we
|
||||
* trigger an access rights trap in user space if the user
|
||||
* tries to read an unreadable page */
|
||||
#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT
|
||||
/* need to drop DMB bit, as it's used as SPECIAL flag */
|
||||
depi 0,_PAGE_SPECIAL_BIT,1,\pte
|
||||
#endif
|
||||
depd \pte,8,7,\prot
|
||||
|
||||
/* PAGE_USER indicates the page can be read with user privileges,
|
||||
@ -529,6 +533,10 @@
|
||||
* makes the tlb entry for the differently formatted pa11
|
||||
* insertion instructions */
|
||||
.macro make_insert_tlb_11 spc,pte,prot
|
||||
#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT
|
||||
/* need to drop DMB bit, as it's used as SPECIAL flag */
|
||||
depi 0,_PAGE_SPECIAL_BIT,1,\pte
|
||||
#endif
|
||||
zdep \spc,30,15,\prot
|
||||
dep \pte,8,7,\prot
|
||||
extru,= \pte,_PAGE_NO_CACHE_BIT,1,%r0
|
||||
|
@ -1,46 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* PDC Console support - ie use firmware to dump text via boot console
|
||||
* PDC early console support - use PDC firmware to dump text via boot console
|
||||
*
|
||||
* Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
|
||||
* Copyright (C) 2000 Martin K Petersen <mkp at mkp.net>
|
||||
* Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
|
||||
* Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
|
||||
* Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
|
||||
* Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
|
||||
* Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
|
||||
* Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
|
||||
* Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
|
||||
* Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
|
||||
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
|
||||
* Copyright (C) 2010 Guy Martin <gmsoft at tuxicoman.be>
|
||||
* Copyright (C) 2001-2022 Helge Deller <deller@gmx.de>
|
||||
*/
|
||||
|
||||
/*
|
||||
* The PDC console is a simple console, which can be used for debugging
|
||||
* boot related problems on HP PA-RISC machines. It is also useful when no
|
||||
* other console works.
|
||||
*
|
||||
* This code uses the ROM (=PDC) based functions to read and write characters
|
||||
* from and to PDC's boot path.
|
||||
*/
|
||||
|
||||
/* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems.
|
||||
* On production kernels EARLY_BOOTUP_DEBUG should be undefined. */
|
||||
#define EARLY_BOOTUP_DEBUG
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/kgdb.h>
|
||||
#include <asm/page.h> /* for PAGE0 */
|
||||
#include <asm/pdc.h> /* for iodc_call() proto and friends */
|
||||
|
||||
static DEFINE_SPINLOCK(pdc_console_lock);
|
||||
static struct console pdc_cons;
|
||||
|
||||
static void pdc_console_write(struct console *co, const char *s, unsigned count)
|
||||
{
|
||||
@ -54,7 +26,8 @@ static void pdc_console_write(struct console *co, const char *s, unsigned count)
|
||||
spin_unlock_irqrestore(&pdc_console_lock, flags);
|
||||
}
|
||||
|
||||
int pdc_console_poll_key(struct console *co)
|
||||
#ifdef CONFIG_KGDB
|
||||
static int kgdb_pdc_read_char(void)
|
||||
{
|
||||
int c;
|
||||
unsigned long flags;
|
||||
@ -63,201 +36,40 @@ int pdc_console_poll_key(struct console *co)
|
||||
c = pdc_iodc_getc();
|
||||
spin_unlock_irqrestore(&pdc_console_lock, flags);
|
||||
|
||||
return c;
|
||||
return (c <= 0) ? NO_POLL_CHAR : c;
|
||||
}
|
||||
|
||||
static int pdc_console_setup(struct console *co, char *options)
|
||||
static void kgdb_pdc_write_char(u8 chr)
|
||||
{
|
||||
return 0;
|
||||
if (PAGE0->mem_cons.cl_class != CL_DUPLEX)
|
||||
pdc_console_write(NULL, &chr, 1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PDC_CONSOLE)
|
||||
#include <linux/vt_kern.h>
|
||||
#include <linux/tty_flip.h>
|
||||
|
||||
#define PDC_CONS_POLL_DELAY (30 * HZ / 1000)
|
||||
|
||||
static void pdc_console_poll(struct timer_list *unused);
|
||||
static DEFINE_TIMER(pdc_console_timer, pdc_console_poll);
|
||||
static struct tty_port tty_port;
|
||||
|
||||
static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
tty_port_tty_set(&tty_port, tty);
|
||||
mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pdc_console_tty_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
if (tty->count == 1) {
|
||||
del_timer_sync(&pdc_console_timer);
|
||||
tty_port_tty_set(&tty_port, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int pdc_console_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
|
||||
{
|
||||
pdc_console_write(NULL, buf, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
static unsigned int pdc_console_tty_write_room(struct tty_struct *tty)
|
||||
{
|
||||
return 32768; /* no limit, no buffer used */
|
||||
}
|
||||
|
||||
static const struct tty_operations pdc_console_tty_ops = {
|
||||
.open = pdc_console_tty_open,
|
||||
.close = pdc_console_tty_close,
|
||||
.write = pdc_console_tty_write,
|
||||
.write_room = pdc_console_tty_write_room,
|
||||
static struct kgdb_io kgdb_pdc_io_ops = {
|
||||
.name = "kgdb_pdc",
|
||||
.read_char = kgdb_pdc_read_char,
|
||||
.write_char = kgdb_pdc_write_char,
|
||||
};
|
||||
|
||||
static void pdc_console_poll(struct timer_list *unused)
|
||||
{
|
||||
int data, count = 0;
|
||||
|
||||
while (1) {
|
||||
data = pdc_console_poll_key(NULL);
|
||||
if (data == -1)
|
||||
break;
|
||||
tty_insert_flip_char(&tty_port, data & 0xFF, TTY_NORMAL);
|
||||
count ++;
|
||||
}
|
||||
|
||||
if (count)
|
||||
tty_flip_buffer_push(&tty_port);
|
||||
|
||||
if (pdc_cons.flags & CON_ENABLED)
|
||||
mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY);
|
||||
}
|
||||
|
||||
static struct tty_driver *pdc_console_tty_driver;
|
||||
|
||||
static int __init pdc_console_tty_driver_init(void)
|
||||
{
|
||||
struct tty_driver *driver;
|
||||
int err;
|
||||
|
||||
/* Check if the console driver is still registered.
|
||||
* It is unregistered if the pdc console was not selected as the
|
||||
* primary console. */
|
||||
|
||||
struct console *tmp;
|
||||
|
||||
console_lock();
|
||||
for_each_console(tmp)
|
||||
if (tmp == &pdc_cons)
|
||||
break;
|
||||
console_unlock();
|
||||
|
||||
if (!tmp) {
|
||||
printk(KERN_INFO "PDC console driver not registered anymore, not creating %s\n", pdc_cons.name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
|
||||
pdc_cons.flags &= ~CON_BOOT;
|
||||
|
||||
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_RESET_TERMIOS);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
tty_port_init(&tty_port);
|
||||
|
||||
driver->driver_name = "pdc_cons";
|
||||
driver->name = "ttyB";
|
||||
driver->major = MUX_MAJOR;
|
||||
driver->minor_start = 0;
|
||||
driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
driver->init_termios = tty_std_termios;
|
||||
tty_set_operations(driver, &pdc_console_tty_ops);
|
||||
tty_port_link_device(&tty_port, driver, 0);
|
||||
|
||||
err = tty_register_driver(driver);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
|
||||
tty_port_destroy(&tty_port);
|
||||
tty_driver_kref_put(driver);
|
||||
return err;
|
||||
}
|
||||
|
||||
pdc_console_tty_driver = driver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(pdc_console_tty_driver_init);
|
||||
|
||||
static struct tty_driver * pdc_console_device (struct console *c, int *index)
|
||||
{
|
||||
*index = c->index;
|
||||
return pdc_console_tty_driver;
|
||||
}
|
||||
#else
|
||||
#define pdc_console_device NULL
|
||||
#endif
|
||||
|
||||
static struct console pdc_cons = {
|
||||
.name = "ttyB",
|
||||
.write = pdc_console_write,
|
||||
.device = pdc_console_device,
|
||||
.setup = pdc_console_setup,
|
||||
.flags = CON_BOOT | CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
static int pdc_console_initialized;
|
||||
|
||||
static void pdc_console_init_force(void)
|
||||
static int __init pdc_earlycon_setup(struct earlycon_device *device,
|
||||
const char *opt)
|
||||
{
|
||||
if (pdc_console_initialized)
|
||||
return;
|
||||
++pdc_console_initialized;
|
||||
|
||||
struct console *earlycon_console;
|
||||
|
||||
/* If the console is duplex then copy the COUT parameters to CIN. */
|
||||
if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
|
||||
memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
|
||||
|
||||
/* register the pdc console */
|
||||
register_console(&pdc_cons);
|
||||
}
|
||||
earlycon_console = device->con;
|
||||
earlycon_console->write = pdc_console_write;
|
||||
device->port.iotype = UPIO_MEM32BE;
|
||||
|
||||
void __init pdc_console_init(void)
|
||||
{
|
||||
#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE)
|
||||
pdc_console_init_force();
|
||||
#endif
|
||||
#ifdef EARLY_BOOTUP_DEBUG
|
||||
printk(KERN_INFO "Initialized PDC Console for debugging.\n");
|
||||
#ifdef CONFIG_KGDB
|
||||
kgdb_register_io_module(&kgdb_pdc_io_ops);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Used for emergencies. Currently only used if an HPMC occurs. If an
|
||||
* HPMC occurs, it is possible that the current console may not be
|
||||
* properly initialised after the PDC IO reset. This routine unregisters
|
||||
* all of the current consoles, reinitializes the pdc console and
|
||||
* registers it.
|
||||
*/
|
||||
|
||||
void pdc_console_restart(void)
|
||||
{
|
||||
struct console *console;
|
||||
|
||||
if (pdc_console_initialized)
|
||||
return;
|
||||
|
||||
/* If we've already seen the output, don't bother to print it again */
|
||||
if (console_drivers != NULL)
|
||||
pdc_cons.flags &= ~CON_PRINTBUFFER;
|
||||
|
||||
while ((console = console_drivers) != NULL)
|
||||
unregister_console(console_drivers);
|
||||
|
||||
/* force registering the pdc console */
|
||||
pdc_console_init_force();
|
||||
}
|
||||
EARLYCON_DECLARE(pdc, pdc_earlycon_setup);
|
||||
|
@ -70,6 +70,10 @@ void __init setup_cmdline(char **cmdline_p)
|
||||
strlcat(p, "tty0", COMMAND_LINE_SIZE);
|
||||
}
|
||||
|
||||
/* default to use early console */
|
||||
if (!strstr(p, "earlycon"))
|
||||
strlcat(p, " earlycon=pdc", COMMAND_LINE_SIZE);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
|
||||
{
|
||||
@ -139,8 +143,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
if (__pa((unsigned long) &_end) >= KERNEL_INITIAL_SIZE)
|
||||
panic("KERNEL_INITIAL_ORDER too small!");
|
||||
|
||||
pdc_console_init();
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
if(parisc_narrow_firmware) {
|
||||
printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
|
||||
|
@ -239,13 +239,6 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
|
||||
/* unlock the pdc lock if necessary */
|
||||
pdc_emergency_unlock();
|
||||
|
||||
/* maybe the kernel hasn't booted very far yet and hasn't been able
|
||||
* to initialize the serial or STI console. In that case we should
|
||||
* re-enable the pdc console, so that the user will be able to
|
||||
* identify the problem. */
|
||||
if (!console_drivers)
|
||||
pdc_console_restart();
|
||||
|
||||
if (err)
|
||||
printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
|
||||
current->comm, task_pid_nr(current), str, err);
|
||||
@ -429,10 +422,6 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o
|
||||
/* unlock the pdc lock if necessary */
|
||||
pdc_emergency_unlock();
|
||||
|
||||
/* restart pdc console if necessary */
|
||||
if (!console_drivers)
|
||||
pdc_console_restart();
|
||||
|
||||
/* Not all paths will gutter the processor... */
|
||||
switch(code){
|
||||
|
||||
@ -482,9 +471,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
||||
unsigned long fault_space = 0;
|
||||
int si_code;
|
||||
|
||||
if (code == 1)
|
||||
pdc_console_restart(); /* switch back to pdc if HPMC */
|
||||
else if (!irqs_disabled_flags(regs->gr[0]))
|
||||
if (!irqs_disabled_flags(regs->gr[0]))
|
||||
local_irq_enable();
|
||||
|
||||
/* Security check:
|
||||
|
@ -89,6 +89,22 @@ long compat_sys_rt_sigreturn(void);
|
||||
* responsible for combining parameter pairs.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
long sys_ppc_pread64(unsigned int fd,
|
||||
char __user *ubuf, compat_size_t count,
|
||||
u32 reg6, u32 pos1, u32 pos2);
|
||||
long sys_ppc_pwrite64(unsigned int fd,
|
||||
const char __user *ubuf, compat_size_t count,
|
||||
u32 reg6, u32 pos1, u32 pos2);
|
||||
long sys_ppc_readahead(int fd, u32 r4,
|
||||
u32 offset1, u32 offset2, u32 count);
|
||||
long sys_ppc_truncate64(const char __user *path, u32 reg4,
|
||||
unsigned long len1, unsigned long len2);
|
||||
long sys_ppc_ftruncate64(unsigned int fd, u32 reg4,
|
||||
unsigned long len1, unsigned long len2);
|
||||
long sys_ppc32_fadvise64(int fd, u32 unused, u32 offset1, u32 offset2,
|
||||
size_t len, int advice);
|
||||
#endif
|
||||
#ifdef CONFIG_COMPAT
|
||||
long compat_sys_mmap2(unsigned long addr, size_t len,
|
||||
unsigned long prot, unsigned long flags,
|
||||
|
@ -73,6 +73,7 @@ obj-y := cputable.o syscalls.o \
|
||||
obj-y += ptrace/
|
||||
obj-$(CONFIG_PPC64) += setup_64.o irq_64.o\
|
||||
paca.o nvram_64.o note.o
|
||||
obj-$(CONFIG_PPC32) += sys_ppc32.o
|
||||
obj-$(CONFIG_COMPAT) += sys_ppc32.o signal_32.o
|
||||
obj-$(CONFIG_VDSO32) += vdso32_wrapper.o
|
||||
obj-$(CONFIG_PPC_WATCHDOG) += watchdog.o
|
||||
|
@ -538,7 +538,7 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
|
||||
beq .Lfast_kernel_interrupt_return_\srr\() // EE already disabled
|
||||
lbz r11,PACAIRQHAPPENED(r13)
|
||||
andi. r10,r11,PACA_IRQ_MUST_HARD_MASK
|
||||
beq 1f // No HARD_MASK pending
|
||||
beq .Lfast_kernel_interrupt_return_\srr\() // No HARD_MASK pending
|
||||
|
||||
/* Must clear MSR_EE from _MSR */
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
@ -555,12 +555,23 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
|
||||
b .Lfast_kernel_interrupt_return_\srr\()
|
||||
|
||||
.Linterrupt_return_\srr\()_soft_enabled:
|
||||
/*
|
||||
* In the soft-enabled case, need to double-check that we have no
|
||||
* pending interrupts that might have come in before we reached the
|
||||
* restart section of code, and restart the exit so those can be
|
||||
* handled.
|
||||
*
|
||||
* If there are none, it is be possible that the interrupt still
|
||||
* has PACA_IRQ_HARD_DIS set, which needs to be cleared for the
|
||||
* interrupted context. This clear will not clobber a new pending
|
||||
* interrupt coming in, because we're in the restart section, so
|
||||
* such would return to the restart location.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
lbz r11,PACAIRQHAPPENED(r13)
|
||||
andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
|
||||
bne- interrupt_return_\srr\()_kernel_restart
|
||||
#endif
|
||||
1:
|
||||
li r11,0
|
||||
stb r11,PACAIRQHAPPENED(r13) // clear the possible HARD_DIS
|
||||
|
||||
|
@ -1,13 +1,23 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* sys_ppc32.c: Conversion between 32bit and 64bit native syscalls.
|
||||
* sys_ppc32.c: 32-bit system calls with complex calling conventions.
|
||||
*
|
||||
* Copyright (C) 2001 IBM
|
||||
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
||||
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
|
||||
*
|
||||
* These routines maintain argument size conversion between 32bit and 64bit
|
||||
* environment.
|
||||
* 32-bit system calls with 64-bit arguments pass those in register pairs.
|
||||
* This must be specially dealt with on 64-bit kernels. The compat_arg_u64_dual
|
||||
* in generic compat syscalls is not always usable because the register
|
||||
* pairing is constrained depending on preceding arguments.
|
||||
*
|
||||
* An analogous problem exists on 32-bit kernels with ARCH_HAS_SYSCALL_WRAPPER,
|
||||
* the defined system call functions take the pt_regs as an argument, and there
|
||||
* is a mapping macro which maps registers to arguments
|
||||
* (SC_POWERPC_REGS_TO_ARGS) which also does not deal with these 64-bit
|
||||
* arguments.
|
||||
*
|
||||
* This file contains these system calls.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -47,7 +57,17 @@
|
||||
#include <asm/syscalls.h>
|
||||
#include <asm/switch_to.h>
|
||||
|
||||
COMPAT_SYSCALL_DEFINE6(ppc_pread64,
|
||||
#ifdef CONFIG_PPC32
|
||||
#define PPC32_SYSCALL_DEFINE4 SYSCALL_DEFINE4
|
||||
#define PPC32_SYSCALL_DEFINE5 SYSCALL_DEFINE5
|
||||
#define PPC32_SYSCALL_DEFINE6 SYSCALL_DEFINE6
|
||||
#else
|
||||
#define PPC32_SYSCALL_DEFINE4 COMPAT_SYSCALL_DEFINE4
|
||||
#define PPC32_SYSCALL_DEFINE5 COMPAT_SYSCALL_DEFINE5
|
||||
#define PPC32_SYSCALL_DEFINE6 COMPAT_SYSCALL_DEFINE6
|
||||
#endif
|
||||
|
||||
PPC32_SYSCALL_DEFINE6(ppc_pread64,
|
||||
unsigned int, fd,
|
||||
char __user *, ubuf, compat_size_t, count,
|
||||
u32, reg6, u32, pos1, u32, pos2)
|
||||
@ -55,7 +75,7 @@ COMPAT_SYSCALL_DEFINE6(ppc_pread64,
|
||||
return ksys_pread64(fd, ubuf, count, merge_64(pos1, pos2));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE6(ppc_pwrite64,
|
||||
PPC32_SYSCALL_DEFINE6(ppc_pwrite64,
|
||||
unsigned int, fd,
|
||||
const char __user *, ubuf, compat_size_t, count,
|
||||
u32, reg6, u32, pos1, u32, pos2)
|
||||
@ -63,28 +83,28 @@ COMPAT_SYSCALL_DEFINE6(ppc_pwrite64,
|
||||
return ksys_pwrite64(fd, ubuf, count, merge_64(pos1, pos2));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE5(ppc_readahead,
|
||||
PPC32_SYSCALL_DEFINE5(ppc_readahead,
|
||||
int, fd, u32, r4,
|
||||
u32, offset1, u32, offset2, u32, count)
|
||||
{
|
||||
return ksys_readahead(fd, merge_64(offset1, offset2), count);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE4(ppc_truncate64,
|
||||
PPC32_SYSCALL_DEFINE4(ppc_truncate64,
|
||||
const char __user *, path, u32, reg4,
|
||||
unsigned long, len1, unsigned long, len2)
|
||||
{
|
||||
return ksys_truncate(path, merge_64(len1, len2));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE4(ppc_ftruncate64,
|
||||
PPC32_SYSCALL_DEFINE4(ppc_ftruncate64,
|
||||
unsigned int, fd, u32, reg4,
|
||||
unsigned long, len1, unsigned long, len2)
|
||||
{
|
||||
return ksys_ftruncate(fd, merge_64(len1, len2));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE6(ppc32_fadvise64,
|
||||
PPC32_SYSCALL_DEFINE6(ppc32_fadvise64,
|
||||
int, fd, u32, unused, u32, offset1, u32, offset2,
|
||||
size_t, len, int, advice)
|
||||
{
|
||||
|
@ -228,8 +228,10 @@
|
||||
176 64 rt_sigtimedwait sys_rt_sigtimedwait
|
||||
177 nospu rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
|
||||
178 nospu rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
|
||||
179 common pread64 sys_pread64 compat_sys_ppc_pread64
|
||||
180 common pwrite64 sys_pwrite64 compat_sys_ppc_pwrite64
|
||||
179 32 pread64 sys_ppc_pread64 compat_sys_ppc_pread64
|
||||
179 64 pread64 sys_pread64
|
||||
180 32 pwrite64 sys_ppc_pwrite64 compat_sys_ppc_pwrite64
|
||||
180 64 pwrite64 sys_pwrite64
|
||||
181 common chown sys_chown
|
||||
182 common getcwd sys_getcwd
|
||||
183 common capget sys_capget
|
||||
@ -242,10 +244,11 @@
|
||||
188 common putpmsg sys_ni_syscall
|
||||
189 nospu vfork sys_vfork
|
||||
190 common ugetrlimit sys_getrlimit compat_sys_getrlimit
|
||||
191 common readahead sys_readahead compat_sys_ppc_readahead
|
||||
191 32 readahead sys_ppc_readahead compat_sys_ppc_readahead
|
||||
191 64 readahead sys_readahead
|
||||
192 32 mmap2 sys_mmap2 compat_sys_mmap2
|
||||
193 32 truncate64 sys_truncate64 compat_sys_ppc_truncate64
|
||||
194 32 ftruncate64 sys_ftruncate64 compat_sys_ppc_ftruncate64
|
||||
193 32 truncate64 sys_ppc_truncate64 compat_sys_ppc_truncate64
|
||||
194 32 ftruncate64 sys_ppc_ftruncate64 compat_sys_ppc_ftruncate64
|
||||
195 32 stat64 sys_stat64
|
||||
196 32 lstat64 sys_lstat64
|
||||
197 32 fstat64 sys_fstat64
|
||||
@ -288,7 +291,8 @@
|
||||
230 common io_submit sys_io_submit compat_sys_io_submit
|
||||
231 common io_cancel sys_io_cancel
|
||||
232 nospu set_tid_address sys_set_tid_address
|
||||
233 common fadvise64 sys_fadvise64 compat_sys_ppc32_fadvise64
|
||||
233 32 fadvise64 sys_ppc32_fadvise64 compat_sys_ppc32_fadvise64
|
||||
233 64 fadvise64 sys_fadvise64
|
||||
234 nospu exit_group sys_exit_group
|
||||
235 nospu lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
|
||||
236 common epoll_create sys_epoll_create
|
||||
|
@ -508,10 +508,10 @@ unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
|
||||
static int __kvmppc_svm_page_out(struct vm_area_struct *vma,
|
||||
unsigned long start,
|
||||
unsigned long end, unsigned long page_shift,
|
||||
struct kvm *kvm, unsigned long gpa)
|
||||
struct kvm *kvm, unsigned long gpa, struct page *fault_page)
|
||||
{
|
||||
unsigned long src_pfn, dst_pfn = 0;
|
||||
struct migrate_vma mig;
|
||||
struct migrate_vma mig = { 0 };
|
||||
struct page *dpage, *spage;
|
||||
struct kvmppc_uvmem_page_pvt *pvt;
|
||||
unsigned long pfn;
|
||||
@ -525,6 +525,7 @@ static int __kvmppc_svm_page_out(struct vm_area_struct *vma,
|
||||
mig.dst = &dst_pfn;
|
||||
mig.pgmap_owner = &kvmppc_uvmem_pgmap;
|
||||
mig.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
|
||||
mig.fault_page = fault_page;
|
||||
|
||||
/* The requested page is already paged-out, nothing to do */
|
||||
if (!kvmppc_gfn_is_uvmem_pfn(gpa >> page_shift, kvm, NULL))
|
||||
@ -580,12 +581,14 @@ static int __kvmppc_svm_page_out(struct vm_area_struct *vma,
|
||||
static inline int kvmppc_svm_page_out(struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end,
|
||||
unsigned long page_shift,
|
||||
struct kvm *kvm, unsigned long gpa)
|
||||
struct kvm *kvm, unsigned long gpa,
|
||||
struct page *fault_page)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&kvm->arch.uvmem_lock);
|
||||
ret = __kvmppc_svm_page_out(vma, start, end, page_shift, kvm, gpa);
|
||||
ret = __kvmppc_svm_page_out(vma, start, end, page_shift, kvm, gpa,
|
||||
fault_page);
|
||||
mutex_unlock(&kvm->arch.uvmem_lock);
|
||||
|
||||
return ret;
|
||||
@ -634,7 +637,7 @@ void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *slot,
|
||||
pvt->remove_gfn = true;
|
||||
|
||||
if (__kvmppc_svm_page_out(vma, addr, addr + PAGE_SIZE,
|
||||
PAGE_SHIFT, kvm, pvt->gpa))
|
||||
PAGE_SHIFT, kvm, pvt->gpa, NULL))
|
||||
pr_err("Can't page out gpa:0x%lx addr:0x%lx\n",
|
||||
pvt->gpa, addr);
|
||||
} else {
|
||||
@ -715,7 +718,7 @@ static struct page *kvmppc_uvmem_get_page(unsigned long gpa, struct kvm *kvm)
|
||||
|
||||
dpage = pfn_to_page(uvmem_pfn);
|
||||
dpage->zone_device_data = pvt;
|
||||
lock_page(dpage);
|
||||
zone_device_page_init(dpage);
|
||||
return dpage;
|
||||
out_clear:
|
||||
spin_lock(&kvmppc_uvmem_bitmap_lock);
|
||||
@ -736,7 +739,7 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma,
|
||||
bool pagein)
|
||||
{
|
||||
unsigned long src_pfn, dst_pfn = 0;
|
||||
struct migrate_vma mig;
|
||||
struct migrate_vma mig = { 0 };
|
||||
struct page *spage;
|
||||
unsigned long pfn;
|
||||
struct page *dpage;
|
||||
@ -994,7 +997,7 @@ static vm_fault_t kvmppc_uvmem_migrate_to_ram(struct vm_fault *vmf)
|
||||
|
||||
if (kvmppc_svm_page_out(vmf->vma, vmf->address,
|
||||
vmf->address + PAGE_SIZE, PAGE_SHIFT,
|
||||
pvt->kvm, pvt->gpa))
|
||||
pvt->kvm, pvt->gpa, vmf->page))
|
||||
return VM_FAULT_SIGBUS;
|
||||
else
|
||||
return 0;
|
||||
@ -1065,7 +1068,7 @@ kvmppc_h_svm_page_out(struct kvm *kvm, unsigned long gpa,
|
||||
if (!vma || vma->vm_start > start || vma->vm_end < end)
|
||||
goto out;
|
||||
|
||||
if (!kvmppc_svm_page_out(vma, start, end, page_shift, kvm, gpa))
|
||||
if (!kvmppc_svm_page_out(vma, start, end, page_shift, kvm, gpa, NULL))
|
||||
ret = H_SUCCESS;
|
||||
out:
|
||||
mmap_read_unlock(kvm->mm);
|
||||
|
@ -7,7 +7,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \
|
||||
setup.o iommu.o event_sources.o ras.o \
|
||||
firmware.o power.o dlpar.o mobility.o rng.o \
|
||||
pci.o pci_dlpar.o eeh_pseries.o msi.o \
|
||||
papr_platform_attributes.o
|
||||
papr_platform_attributes.o dtl.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_KEXEC_CORE) += kexec.o
|
||||
obj-$(CONFIG_PSERIES_ENERGY) += pseries_energy.o
|
||||
@ -19,7 +19,6 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
|
||||
obj-$(CONFIG_HVCS) += hvcserver.o
|
||||
obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
|
||||
obj-$(CONFIG_CMM) += cmm.o
|
||||
obj-$(CONFIG_DTL) += dtl.o
|
||||
obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o
|
||||
obj-$(CONFIG_LPARCFG) += lparcfg.o
|
||||
obj-$(CONFIG_IBMVIO) += vio.o
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <asm/plpar_wrappers.h>
|
||||
#include <asm/machdep.h>
|
||||
|
||||
#ifdef CONFIG_DTL
|
||||
struct dtl {
|
||||
struct dtl_entry *buf;
|
||||
int cpu;
|
||||
@ -57,78 +58,6 @@ static DEFINE_PER_CPU(struct dtl_ring, dtl_rings);
|
||||
|
||||
static atomic_t dtl_count;
|
||||
|
||||
/*
|
||||
* Scan the dispatch trace log and count up the stolen time.
|
||||
* Should be called with interrupts disabled.
|
||||
*/
|
||||
static notrace u64 scan_dispatch_log(u64 stop_tb)
|
||||
{
|
||||
u64 i = local_paca->dtl_ridx;
|
||||
struct dtl_entry *dtl = local_paca->dtl_curr;
|
||||
struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
|
||||
struct lppaca *vpa = local_paca->lppaca_ptr;
|
||||
u64 tb_delta;
|
||||
u64 stolen = 0;
|
||||
u64 dtb;
|
||||
|
||||
if (!dtl)
|
||||
return 0;
|
||||
|
||||
if (i == be64_to_cpu(vpa->dtl_idx))
|
||||
return 0;
|
||||
while (i < be64_to_cpu(vpa->dtl_idx)) {
|
||||
dtb = be64_to_cpu(dtl->timebase);
|
||||
tb_delta = be32_to_cpu(dtl->enqueue_to_dispatch_time) +
|
||||
be32_to_cpu(dtl->ready_to_enqueue_time);
|
||||
barrier();
|
||||
if (i + N_DISPATCH_LOG < be64_to_cpu(vpa->dtl_idx)) {
|
||||
/* buffer has overflowed */
|
||||
i = be64_to_cpu(vpa->dtl_idx) - N_DISPATCH_LOG;
|
||||
dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
|
||||
continue;
|
||||
}
|
||||
if (dtb > stop_tb)
|
||||
break;
|
||||
if (dtl_consumer)
|
||||
dtl_consumer(dtl, i);
|
||||
stolen += tb_delta;
|
||||
++i;
|
||||
++dtl;
|
||||
if (dtl == dtl_end)
|
||||
dtl = local_paca->dispatch_log;
|
||||
}
|
||||
local_paca->dtl_ridx = i;
|
||||
local_paca->dtl_curr = dtl;
|
||||
return stolen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accumulate stolen time by scanning the dispatch trace log.
|
||||
* Called on entry from user mode.
|
||||
*/
|
||||
void notrace pseries_accumulate_stolen_time(void)
|
||||
{
|
||||
u64 sst, ust;
|
||||
struct cpu_accounting_data *acct = &local_paca->accounting;
|
||||
|
||||
sst = scan_dispatch_log(acct->starttime_user);
|
||||
ust = scan_dispatch_log(acct->starttime);
|
||||
acct->stime -= sst;
|
||||
acct->utime -= ust;
|
||||
acct->steal_time += ust + sst;
|
||||
}
|
||||
|
||||
u64 pseries_calculate_stolen_time(u64 stop_tb)
|
||||
{
|
||||
if (!firmware_has_feature(FW_FEATURE_SPLPAR))
|
||||
return 0;
|
||||
|
||||
if (get_paca()->dtl_ridx != be64_to_cpu(get_lppaca()->dtl_idx))
|
||||
return scan_dispatch_log(stop_tb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The cpu accounting code controls the DTL ring buffer, and we get
|
||||
* given entries as they are processed.
|
||||
@ -436,3 +365,81 @@ static int dtl_init(void)
|
||||
return 0;
|
||||
}
|
||||
machine_arch_initcall(pseries, dtl_init);
|
||||
#endif /* CONFIG_DTL */
|
||||
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
|
||||
/*
|
||||
* Scan the dispatch trace log and count up the stolen time.
|
||||
* Should be called with interrupts disabled.
|
||||
*/
|
||||
static notrace u64 scan_dispatch_log(u64 stop_tb)
|
||||
{
|
||||
u64 i = local_paca->dtl_ridx;
|
||||
struct dtl_entry *dtl = local_paca->dtl_curr;
|
||||
struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
|
||||
struct lppaca *vpa = local_paca->lppaca_ptr;
|
||||
u64 tb_delta;
|
||||
u64 stolen = 0;
|
||||
u64 dtb;
|
||||
|
||||
if (!dtl)
|
||||
return 0;
|
||||
|
||||
if (i == be64_to_cpu(vpa->dtl_idx))
|
||||
return 0;
|
||||
while (i < be64_to_cpu(vpa->dtl_idx)) {
|
||||
dtb = be64_to_cpu(dtl->timebase);
|
||||
tb_delta = be32_to_cpu(dtl->enqueue_to_dispatch_time) +
|
||||
be32_to_cpu(dtl->ready_to_enqueue_time);
|
||||
barrier();
|
||||
if (i + N_DISPATCH_LOG < be64_to_cpu(vpa->dtl_idx)) {
|
||||
/* buffer has overflowed */
|
||||
i = be64_to_cpu(vpa->dtl_idx) - N_DISPATCH_LOG;
|
||||
dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
|
||||
continue;
|
||||
}
|
||||
if (dtb > stop_tb)
|
||||
break;
|
||||
#ifdef CONFIG_DTL
|
||||
if (dtl_consumer)
|
||||
dtl_consumer(dtl, i);
|
||||
#endif
|
||||
stolen += tb_delta;
|
||||
++i;
|
||||
++dtl;
|
||||
if (dtl == dtl_end)
|
||||
dtl = local_paca->dispatch_log;
|
||||
}
|
||||
local_paca->dtl_ridx = i;
|
||||
local_paca->dtl_curr = dtl;
|
||||
return stolen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accumulate stolen time by scanning the dispatch trace log.
|
||||
* Called on entry from user mode.
|
||||
*/
|
||||
void notrace pseries_accumulate_stolen_time(void)
|
||||
{
|
||||
u64 sst, ust;
|
||||
struct cpu_accounting_data *acct = &local_paca->accounting;
|
||||
|
||||
sst = scan_dispatch_log(acct->starttime_user);
|
||||
ust = scan_dispatch_log(acct->starttime);
|
||||
acct->stime -= sst;
|
||||
acct->utime -= ust;
|
||||
acct->steal_time += ust + sst;
|
||||
}
|
||||
|
||||
u64 pseries_calculate_stolen_time(u64 stop_tb)
|
||||
{
|
||||
if (!firmware_has_feature(FW_FEATURE_SPLPAR))
|
||||
return 0;
|
||||
|
||||
if (get_paca()->dtl_ridx != be64_to_cpu(get_lppaca()->dtl_idx))
|
||||
return scan_dispatch_log(stop_tb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -70,6 +70,7 @@ config RISCV
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
|
||||
select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO
|
||||
select HARDIRQS_SW_RESEND
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE if !XIP_KERNEL
|
||||
|
@ -37,6 +37,7 @@ else
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LD_IS_LLD),y)
|
||||
ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 150000; echo $$?),0)
|
||||
KBUILD_CFLAGS += -mno-relax
|
||||
KBUILD_AFLAGS += -mno-relax
|
||||
ifndef CONFIG_AS_IS_LLVM
|
||||
@ -44,6 +45,7 @@ ifndef CONFIG_AS_IS_LLVM
|
||||
KBUILD_AFLAGS += -Wa,-mno-relax
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# ISA string setting
|
||||
riscv-march-$(CONFIG_ARCH_RV32I) := rv32ima
|
||||
|
@ -1,4 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
dtb-$(CONFIG_SOC_MICROCHIP_POLARFIRE) += mpfs-icicle-kit.dtb
|
||||
dtb-$(CONFIG_SOC_MICROCHIP_POLARFIRE) += mpfs-m100pfsevp.dtb
|
||||
dtb-$(CONFIG_SOC_MICROCHIP_POLARFIRE) += mpfs-polarberry.dtb
|
||||
dtb-$(CONFIG_SOC_MICROCHIP_POLARFIRE) += mpfs-sev-kit.dtb
|
||||
obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
|
||||
|
@ -2,20 +2,21 @@
|
||||
/* Copyright (c) 2020-2021 Microchip Technology Inc */
|
||||
|
||||
/ {
|
||||
compatible = "microchip,mpfs-icicle-reference-rtlv2203", "microchip,mpfs";
|
||||
compatible = "microchip,mpfs-icicle-reference-rtlv2210", "microchip,mpfs-icicle-kit",
|
||||
"microchip,mpfs";
|
||||
|
||||
core_pwm0: pwm@41000000 {
|
||||
core_pwm0: pwm@40000000 {
|
||||
compatible = "microchip,corepwm-rtl-v4";
|
||||
reg = <0x0 0x41000000 0x0 0xF0>;
|
||||
reg = <0x0 0x40000000 0x0 0xF0>;
|
||||
microchip,sync-update-mask = /bits/ 32 <0>;
|
||||
#pwm-cells = <2>;
|
||||
clocks = <&fabric_clk3>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c2: i2c@44000000 {
|
||||
i2c2: i2c@40000200 {
|
||||
compatible = "microchip,corei2c-rtl-v7";
|
||||
reg = <0x0 0x44000000 0x0 0x1000>;
|
||||
reg = <0x0 0x40000200 0x0 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&fabric_clk3>;
|
||||
@ -28,7 +29,7 @@ i2c2: i2c@44000000 {
|
||||
fabric_clk3: fabric-clk3 {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <62500000>;
|
||||
clock-frequency = <50000000>;
|
||||
};
|
||||
|
||||
fabric_clk1: fabric-clk1 {
|
||||
@ -36,4 +37,34 @@ fabric_clk1: fabric-clk1 {
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <125000000>;
|
||||
};
|
||||
|
||||
pcie: pcie@3000000000 {
|
||||
compatible = "microchip,pcie-host-1.0";
|
||||
#address-cells = <0x3>;
|
||||
#interrupt-cells = <0x1>;
|
||||
#size-cells = <0x2>;
|
||||
device_type = "pci";
|
||||
reg = <0x30 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>;
|
||||
reg-names = "cfg", "apb";
|
||||
bus-range = <0x0 0x7f>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <119>;
|
||||
interrupt-map = <0 0 0 1 &pcie_intc 0>,
|
||||
<0 0 0 2 &pcie_intc 1>,
|
||||
<0 0 0 3 &pcie_intc 2>,
|
||||
<0 0 0 4 &pcie_intc 3>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
clocks = <&fabric_clk1>, <&fabric_clk3>;
|
||||
clock-names = "fic1", "fic3";
|
||||
ranges = <0x3000000 0x0 0x8000000 0x30 0x8000000 0x0 0x80000000>;
|
||||
dma-ranges = <0x02000000 0x0 0x00000000 0x0 0x00000000 0x1 0x00000000>;
|
||||
msi-parent = <&pcie>;
|
||||
msi-controller;
|
||||
status = "disabled";
|
||||
pcie_intc: interrupt-controller {
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -11,7 +11,8 @@
|
||||
|
||||
/ {
|
||||
model = "Microchip PolarFire-SoC Icicle Kit";
|
||||
compatible = "microchip,mpfs-icicle-kit", "microchip,mpfs";
|
||||
compatible = "microchip,mpfs-icicle-reference-rtlv2210", "microchip,mpfs-icicle-kit",
|
||||
"microchip,mpfs";
|
||||
|
||||
aliases {
|
||||
ethernet0 = &mac1;
|
||||
@ -32,15 +33,26 @@ cpus {
|
||||
|
||||
ddrc_cache_lo: memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x80000000 0x0 0x2e000000>;
|
||||
reg = <0x0 0x80000000 0x0 0x40000000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ddrc_cache_hi: memory@1000000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x10 0x0 0x0 0x40000000>;
|
||||
reg = <0x10 0x40000000 0x0 0x40000000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
hss_payload: region@BFC00000 {
|
||||
reg = <0x0 0xBFC00000 0x0 0x400000>;
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&core_pwm0 {
|
||||
|
45
arch/riscv/boot/dts/microchip/mpfs-m100pfs-fabric.dtsi
Normal file
45
arch/riscv/boot/dts/microchip/mpfs-m100pfs-fabric.dtsi
Normal file
@ -0,0 +1,45 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
/* Copyright (c) 2022 Microchip Technology Inc */
|
||||
|
||||
/ {
|
||||
fabric_clk3: fabric-clk3 {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <62500000>;
|
||||
};
|
||||
|
||||
fabric_clk1: fabric-clk1 {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <125000000>;
|
||||
};
|
||||
|
||||
pcie: pcie@2000000000 {
|
||||
compatible = "microchip,pcie-host-1.0";
|
||||
#address-cells = <0x3>;
|
||||
#interrupt-cells = <0x1>;
|
||||
#size-cells = <0x2>;
|
||||
device_type = "pci";
|
||||
reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>;
|
||||
reg-names = "cfg", "apb";
|
||||
bus-range = <0x0 0x7f>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <119>;
|
||||
interrupt-map = <0 0 0 1 &pcie_intc 0>,
|
||||
<0 0 0 2 &pcie_intc 1>,
|
||||
<0 0 0 3 &pcie_intc 2>,
|
||||
<0 0 0 4 &pcie_intc 3>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>;
|
||||
clock-names = "fic0", "fic1", "fic3";
|
||||
ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>;
|
||||
msi-parent = <&pcie>;
|
||||
msi-controller;
|
||||
status = "disabled";
|
||||
pcie_intc: interrupt-controller {
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
};
|
179
arch/riscv/boot/dts/microchip/mpfs-m100pfsevp.dts
Normal file
179
arch/riscv/boot/dts/microchip/mpfs-m100pfsevp.dts
Normal file
@ -0,0 +1,179 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Original all-in-one devicetree:
|
||||
* Copyright (C) 2021-2022 - Wolfgang Grandegger <wg@aries-embedded.de>
|
||||
* Rewritten to use includes:
|
||||
* Copyright (C) 2022 - Conor Dooley <conor.dooley@microchip.com>
|
||||
*/
|
||||
/dts-v1/;
|
||||
|
||||
#include "mpfs.dtsi"
|
||||
#include "mpfs-m100pfs-fabric.dtsi"
|
||||
|
||||
/* Clock frequency (in Hz) of the rtcclk */
|
||||
#define MTIMER_FREQ 1000000
|
||||
|
||||
/ {
|
||||
model = "Aries Embedded M100PFEVPS";
|
||||
compatible = "aries,m100pfsevp", "microchip,mpfs";
|
||||
|
||||
aliases {
|
||||
ethernet0 = &mac0;
|
||||
ethernet1 = &mac1;
|
||||
serial0 = &mmuart0;
|
||||
serial1 = &mmuart1;
|
||||
serial2 = &mmuart2;
|
||||
serial3 = &mmuart3;
|
||||
serial4 = &mmuart4;
|
||||
gpio0 = &gpio0;
|
||||
gpio1 = &gpio2;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial1:115200n8";
|
||||
};
|
||||
|
||||
cpus {
|
||||
timebase-frequency = <MTIMER_FREQ>;
|
||||
};
|
||||
|
||||
ddrc_cache_lo: memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x80000000 0x0 0x40000000>;
|
||||
};
|
||||
ddrc_cache_hi: memory@1040000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x10 0x40000000 0x0 0x40000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&can0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
interrupts = <13>, <14>, <15>, <16>,
|
||||
<17>, <18>, <19>, <20>,
|
||||
<21>, <22>, <23>, <24>,
|
||||
<25>, <26>;
|
||||
ngpios = <14>;
|
||||
status = "okay";
|
||||
|
||||
pmic-irq-hog {
|
||||
gpio-hog;
|
||||
gpios = <13 0>;
|
||||
input;
|
||||
};
|
||||
|
||||
/* Set to low for eMMC, high for SD-card */
|
||||
mmc-sel-hog {
|
||||
gpio-hog;
|
||||
gpios = <12 0>;
|
||||
output-high;
|
||||
};
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
interrupts = <13>, <14>, <15>, <16>,
|
||||
<17>, <18>, <19>, <20>,
|
||||
<21>, <22>, <23>, <24>,
|
||||
<25>, <26>, <27>, <28>,
|
||||
<29>, <30>, <31>, <32>,
|
||||
<33>, <34>, <35>, <36>,
|
||||
<37>, <38>, <39>, <40>,
|
||||
<41>, <42>, <43>, <44>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mac0 {
|
||||
status = "okay";
|
||||
phy-mode = "gmii";
|
||||
phy-handle = <&phy0>;
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&mac1 {
|
||||
status = "okay";
|
||||
phy-mode = "gmii";
|
||||
phy-handle = <&phy1>;
|
||||
phy1: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&mbox {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmc {
|
||||
max-frequency = <50000000>;
|
||||
bus-width = <4>;
|
||||
cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
no-1-8-v;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
disable-wp;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmuart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmuart2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmuart3 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmuart4 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pcie {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qspi {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&refclk {
|
||||
clock-frequency = <125000000>;
|
||||
};
|
||||
|
||||
&rtc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&syscontroller {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
};
|
@ -13,4 +13,33 @@ fabric_clk1: fabric-clk1 {
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <125000000>;
|
||||
};
|
||||
|
||||
pcie: pcie@2000000000 {
|
||||
compatible = "microchip,pcie-host-1.0";
|
||||
#address-cells = <0x3>;
|
||||
#interrupt-cells = <0x1>;
|
||||
#size-cells = <0x2>;
|
||||
device_type = "pci";
|
||||
reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>;
|
||||
reg-names = "cfg", "apb";
|
||||
bus-range = <0x0 0x7f>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <119>;
|
||||
interrupt-map = <0 0 0 1 &pcie_intc 0>,
|
||||
<0 0 0 2 &pcie_intc 1>,
|
||||
<0 0 0 3 &pcie_intc 2>,
|
||||
<0 0 0 4 &pcie_intc 3>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>;
|
||||
clock-names = "fic0", "fic1", "fic3";
|
||||
ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>;
|
||||
msi-parent = <&pcie>;
|
||||
msi-controller;
|
||||
status = "disabled";
|
||||
pcie_intc: interrupt-controller {
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
45
arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi
Normal file
45
arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi
Normal file
@ -0,0 +1,45 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
/* Copyright (c) 2022 Microchip Technology Inc */
|
||||
|
||||
/ {
|
||||
fabric_clk3: fabric-clk3 {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
fabric_clk1: fabric-clk1 {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <125000000>;
|
||||
};
|
||||
|
||||
pcie: pcie@2000000000 {
|
||||
compatible = "microchip,pcie-host-1.0";
|
||||
#address-cells = <0x3>;
|
||||
#interrupt-cells = <0x1>;
|
||||
#size-cells = <0x2>;
|
||||
device_type = "pci";
|
||||
reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>;
|
||||
reg-names = "cfg", "apb";
|
||||
bus-range = <0x0 0x7f>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <119>;
|
||||
interrupt-map = <0 0 0 1 &pcie_intc 0>,
|
||||
<0 0 0 2 &pcie_intc 1>,
|
||||
<0 0 0 3 &pcie_intc 2>,
|
||||
<0 0 0 4 &pcie_intc 3>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>;
|
||||
clock-names = "fic0", "fic1", "fic3";
|
||||
ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>;
|
||||
msi-parent = <&pcie>;
|
||||
msi-controller;
|
||||
status = "disabled";
|
||||
pcie_intc: interrupt-controller {
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
};
|
145
arch/riscv/boot/dts/microchip/mpfs-sev-kit.dts
Normal file
145
arch/riscv/boot/dts/microchip/mpfs-sev-kit.dts
Normal file
@ -0,0 +1,145 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
/* Copyright (c) 2022 Microchip Technology Inc */
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "mpfs.dtsi"
|
||||
#include "mpfs-sev-kit-fabric.dtsi"
|
||||
|
||||
/* Clock frequency (in Hz) of the rtcclk */
|
||||
#define MTIMER_FREQ 1000000
|
||||
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
model = "Microchip PolarFire-SoC SEV Kit";
|
||||
compatible = "microchip,mpfs-sev-kit", "microchip,mpfs";
|
||||
|
||||
aliases {
|
||||
ethernet0 = &mac1;
|
||||
serial0 = &mmuart0;
|
||||
serial1 = &mmuart1;
|
||||
serial2 = &mmuart2;
|
||||
serial3 = &mmuart3;
|
||||
serial4 = &mmuart4;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial1:115200n8";
|
||||
};
|
||||
|
||||
cpus {
|
||||
timebase-frequency = <MTIMER_FREQ>;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
fabricbuf0ddrc: buffer@80000000 {
|
||||
compatible = "shared-dma-pool";
|
||||
reg = <0x0 0x80000000 0x0 0x2000000>;
|
||||
};
|
||||
|
||||
fabricbuf1ddrnc: buffer@c4000000 {
|
||||
compatible = "shared-dma-pool";
|
||||
reg = <0x0 0xc4000000 0x0 0x4000000>;
|
||||
};
|
||||
|
||||
fabricbuf2ddrncwcb: buffer@d4000000 {
|
||||
compatible = "shared-dma-pool";
|
||||
reg = <0x0 0xd4000000 0x0 0x4000000>;
|
||||
};
|
||||
};
|
||||
|
||||
ddrc_cache: memory@1000000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x10 0x0 0x0 0x76000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
interrupts = <53>, <53>, <53>, <53>,
|
||||
<53>, <53>, <53>, <53>,
|
||||
<53>, <53>, <53>, <53>,
|
||||
<53>, <53>, <53>, <53>,
|
||||
<53>, <53>, <53>, <53>,
|
||||
<53>, <53>, <53>, <53>,
|
||||
<53>, <53>, <53>, <53>,
|
||||
<53>, <53>, <53>, <53>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mac0 {
|
||||
status = "okay";
|
||||
phy-mode = "sgmii";
|
||||
phy-handle = <&phy0>;
|
||||
phy1: ethernet-phy@9 {
|
||||
reg = <9>;
|
||||
};
|
||||
phy0: ethernet-phy@8 {
|
||||
reg = <8>;
|
||||
};
|
||||
};
|
||||
|
||||
&mac1 {
|
||||
status = "okay";
|
||||
phy-mode = "sgmii";
|
||||
phy-handle = <&phy1>;
|
||||
};
|
||||
|
||||
&mbox {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmc {
|
||||
status = "okay";
|
||||
bus-width = <4>;
|
||||
disable-wp;
|
||||
cap-sd-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
mmc-ddr-1_8v;
|
||||
mmc-hs200-1_8v;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
};
|
||||
|
||||
&mmuart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmuart2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmuart3 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mmuart4 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&refclk {
|
||||
clock-frequency = <125000000>;
|
||||
};
|
||||
|
||||
&rtc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&syscontroller {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb {
|
||||
status = "okay";
|
||||
dr_mode = "otg";
|
||||
};
|
@ -330,7 +330,7 @@ spi1: spi@20109000 {
|
||||
};
|
||||
|
||||
qspi: spi@21000000 {
|
||||
compatible = "microchip,mpfs-qspi";
|
||||
compatible = "microchip,mpfs-qspi", "microchip,coreqspi-rtl-v2";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x0 0x21000000 0x0 0x1000>;
|
||||
@ -464,35 +464,6 @@ usb: usb@20201000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcie: pcie@2000000000 {
|
||||
compatible = "microchip,pcie-host-1.0";
|
||||
#address-cells = <0x3>;
|
||||
#interrupt-cells = <0x1>;
|
||||
#size-cells = <0x2>;
|
||||
device_type = "pci";
|
||||
reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>;
|
||||
reg-names = "cfg", "apb";
|
||||
bus-range = <0x0 0x7f>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <119>;
|
||||
interrupt-map = <0 0 0 1 &pcie_intc 0>,
|
||||
<0 0 0 2 &pcie_intc 1>,
|
||||
<0 0 0 3 &pcie_intc 2>,
|
||||
<0 0 0 4 &pcie_intc 3>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>;
|
||||
clock-names = "fic0", "fic1", "fic3";
|
||||
ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>;
|
||||
msi-parent = <&pcie>;
|
||||
msi-controller;
|
||||
status = "disabled";
|
||||
pcie_intc: interrupt-controller {
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
|
||||
mbox: mailbox@37020000 {
|
||||
compatible = "microchip,mpfs-mailbox";
|
||||
reg = <0x0 0x37020000 0x0 0x1000>, <0x0 0x2000318C 0x0 0x40>;
|
||||
|
@ -17,6 +17,9 @@
|
||||
static bool errata_probe_pbmt(unsigned int stage,
|
||||
unsigned long arch_id, unsigned long impid)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PBMT))
|
||||
return false;
|
||||
|
||||
if (arch_id != 0 || impid != 0)
|
||||
return false;
|
||||
|
||||
@ -30,7 +33,9 @@ static bool errata_probe_pbmt(unsigned int stage,
|
||||
static bool errata_probe_cmo(unsigned int stage,
|
||||
unsigned long arch_id, unsigned long impid)
|
||||
{
|
||||
#ifdef CONFIG_ERRATA_THEAD_CMO
|
||||
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_CMO))
|
||||
return false;
|
||||
|
||||
if (arch_id != 0 || impid != 0)
|
||||
return false;
|
||||
|
||||
@ -40,9 +45,6 @@ static bool errata_probe_cmo(unsigned int stage,
|
||||
riscv_cbom_block_size = L1_CACHE_BYTES;
|
||||
riscv_noncoherent_supported();
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static u32 thead_errata_probe(unsigned int stage,
|
||||
@ -51,10 +53,10 @@ static u32 thead_errata_probe(unsigned int stage,
|
||||
u32 cpu_req_errata = 0;
|
||||
|
||||
if (errata_probe_pbmt(stage, archid, impid))
|
||||
cpu_req_errata |= (1U << ERRATA_THEAD_PBMT);
|
||||
cpu_req_errata |= BIT(ERRATA_THEAD_PBMT);
|
||||
|
||||
if (errata_probe_cmo(stage, archid, impid))
|
||||
cpu_req_errata |= (1U << ERRATA_THEAD_CMO);
|
||||
cpu_req_errata |= BIT(ERRATA_THEAD_CMO);
|
||||
|
||||
return cpu_req_errata;
|
||||
}
|
||||
|
@ -55,6 +55,8 @@ static inline void riscv_init_cbom_blocksize(void) { }
|
||||
|
||||
#ifdef CONFIG_RISCV_DMA_NONCOHERENT
|
||||
void riscv_noncoherent_supported(void);
|
||||
#else
|
||||
static inline void riscv_noncoherent_supported(void) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -99,6 +99,10 @@ do { \
|
||||
get_cache_size(2, CACHE_TYPE_UNIFIED)); \
|
||||
NEW_AUX_ENT(AT_L2_CACHEGEOMETRY, \
|
||||
get_cache_geometry(2, CACHE_TYPE_UNIFIED)); \
|
||||
NEW_AUX_ENT(AT_L3_CACHESIZE, \
|
||||
get_cache_size(3, CACHE_TYPE_UNIFIED)); \
|
||||
NEW_AUX_ENT(AT_L3_CACHEGEOMETRY, \
|
||||
get_cache_geometry(3, CACHE_TYPE_UNIFIED)); \
|
||||
} while (0)
|
||||
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
||||
struct linux_binprm;
|
||||
|
@ -101,9 +101,9 @@ __io_reads_ins(reads, u32, l, __io_br(), __io_ar(addr))
|
||||
__io_reads_ins(ins, u8, b, __io_pbr(), __io_par(addr))
|
||||
__io_reads_ins(ins, u16, w, __io_pbr(), __io_par(addr))
|
||||
__io_reads_ins(ins, u32, l, __io_pbr(), __io_par(addr))
|
||||
#define insb(addr, buffer, count) __insb((void __iomem *)(long)addr, buffer, count)
|
||||
#define insw(addr, buffer, count) __insw((void __iomem *)(long)addr, buffer, count)
|
||||
#define insl(addr, buffer, count) __insl((void __iomem *)(long)addr, buffer, count)
|
||||
#define insb(addr, buffer, count) __insb(PCI_IOBASE + (addr), buffer, count)
|
||||
#define insw(addr, buffer, count) __insw(PCI_IOBASE + (addr), buffer, count)
|
||||
#define insl(addr, buffer, count) __insl(PCI_IOBASE + (addr), buffer, count)
|
||||
|
||||
__io_writes_outs(writes, u8, b, __io_bw(), __io_aw())
|
||||
__io_writes_outs(writes, u16, w, __io_bw(), __io_aw())
|
||||
@ -115,22 +115,22 @@ __io_writes_outs(writes, u32, l, __io_bw(), __io_aw())
|
||||
__io_writes_outs(outs, u8, b, __io_pbw(), __io_paw())
|
||||
__io_writes_outs(outs, u16, w, __io_pbw(), __io_paw())
|
||||
__io_writes_outs(outs, u32, l, __io_pbw(), __io_paw())
|
||||
#define outsb(addr, buffer, count) __outsb((void __iomem *)(long)addr, buffer, count)
|
||||
#define outsw(addr, buffer, count) __outsw((void __iomem *)(long)addr, buffer, count)
|
||||
#define outsl(addr, buffer, count) __outsl((void __iomem *)(long)addr, buffer, count)
|
||||
#define outsb(addr, buffer, count) __outsb(PCI_IOBASE + (addr), buffer, count)
|
||||
#define outsw(addr, buffer, count) __outsw(PCI_IOBASE + (addr), buffer, count)
|
||||
#define outsl(addr, buffer, count) __outsl(PCI_IOBASE + (addr), buffer, count)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
__io_reads_ins(reads, u64, q, __io_br(), __io_ar(addr))
|
||||
#define readsq(addr, buffer, count) __readsq(addr, buffer, count)
|
||||
|
||||
__io_reads_ins(ins, u64, q, __io_pbr(), __io_par(addr))
|
||||
#define insq(addr, buffer, count) __insq((void __iomem *)addr, buffer, count)
|
||||
#define insq(addr, buffer, count) __insq(PCI_IOBASE + (addr), buffer, count)
|
||||
|
||||
__io_writes_outs(writes, u64, q, __io_bw(), __io_aw())
|
||||
#define writesq(addr, buffer, count) __writesq(addr, buffer, count)
|
||||
|
||||
__io_writes_outs(outs, u64, q, __io_pbr(), __io_paw())
|
||||
#define outsq(addr, buffer, count) __outsq((void __iomem *)addr, buffer, count)
|
||||
#define outsq(addr, buffer, count) __outsq(PCI_IOBASE + (addr), buffer, count)
|
||||
#endif
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
@ -16,7 +16,6 @@ typedef struct {
|
||||
atomic_long_t id;
|
||||
#endif
|
||||
void *vdso;
|
||||
void *vdso_info;
|
||||
#ifdef CONFIG_SMP
|
||||
/* A local icache flush is needed before user execution can resume. */
|
||||
cpumask_t icache_stale_mask;
|
||||
|
@ -30,8 +30,10 @@
|
||||
#define AT_L1D_CACHEGEOMETRY 43
|
||||
#define AT_L2_CACHESIZE 44
|
||||
#define AT_L2_CACHEGEOMETRY 45
|
||||
#define AT_L3_CACHESIZE 46
|
||||
#define AT_L3_CACHEGEOMETRY 47
|
||||
|
||||
/* entries in ARCH_DLINFO */
|
||||
#define AT_VECTOR_SIZE_ARCH 7
|
||||
#define AT_VECTOR_SIZE_ARCH 9
|
||||
|
||||
#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
|
||||
|
@ -3,10 +3,13 @@
|
||||
* Copyright (C) 2012 Regents of the University of California
|
||||
*/
|
||||
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/of.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
@ -68,6 +71,50 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
struct riscv_cpuinfo {
|
||||
unsigned long mvendorid;
|
||||
unsigned long marchid;
|
||||
unsigned long mimpid;
|
||||
};
|
||||
static DEFINE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
|
||||
|
||||
static int riscv_cpuinfo_starting(unsigned int cpu)
|
||||
{
|
||||
struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo);
|
||||
|
||||
#if IS_ENABLED(CONFIG_RISCV_SBI)
|
||||
ci->mvendorid = sbi_spec_is_0_1() ? 0 : sbi_get_mvendorid();
|
||||
ci->marchid = sbi_spec_is_0_1() ? 0 : sbi_get_marchid();
|
||||
ci->mimpid = sbi_spec_is_0_1() ? 0 : sbi_get_mimpid();
|
||||
#elif IS_ENABLED(CONFIG_RISCV_M_MODE)
|
||||
ci->mvendorid = csr_read(CSR_MVENDORID);
|
||||
ci->marchid = csr_read(CSR_MARCHID);
|
||||
ci->mimpid = csr_read(CSR_MIMPID);
|
||||
#else
|
||||
ci->mvendorid = 0;
|
||||
ci->marchid = 0;
|
||||
ci->mimpid = 0;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init riscv_cpuinfo_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "riscv/cpuinfo:starting",
|
||||
riscv_cpuinfo_starting, NULL);
|
||||
if (ret < 0) {
|
||||
pr_err("cpuinfo: failed to register hotplug callbacks.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(riscv_cpuinfo_init);
|
||||
|
||||
#define __RISCV_ISA_EXT_DATA(UPROP, EXTID) \
|
||||
{ \
|
||||
.uprop = #UPROP, \
|
||||
@ -186,6 +233,7 @@ static int c_show(struct seq_file *m, void *v)
|
||||
{
|
||||
unsigned long cpu_id = (unsigned long)v - 1;
|
||||
struct device_node *node = of_get_cpu_node(cpu_id, NULL);
|
||||
struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id);
|
||||
const char *compat, *isa;
|
||||
|
||||
seq_printf(m, "processor\t: %lu\n", cpu_id);
|
||||
@ -196,6 +244,9 @@ static int c_show(struct seq_file *m, void *v)
|
||||
if (!of_property_read_string(node, "compatible", &compat)
|
||||
&& strcmp(compat, "riscv"))
|
||||
seq_printf(m, "uarch\t\t: %s\n", compat);
|
||||
seq_printf(m, "mvendorid\t: 0x%lx\n", ci->mvendorid);
|
||||
seq_printf(m, "marchid\t\t: 0x%lx\n", ci->marchid);
|
||||
seq_printf(m, "mimpid\t\t: 0x%lx\n", ci->mimpid);
|
||||
seq_puts(m, "\n");
|
||||
of_node_put(node);
|
||||
|
||||
|
@ -254,35 +254,28 @@ void __init riscv_fill_hwcap(void)
|
||||
#ifdef CONFIG_RISCV_ALTERNATIVE
|
||||
static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage)
|
||||
{
|
||||
#ifdef CONFIG_RISCV_ISA_SVPBMT
|
||||
switch (stage) {
|
||||
case RISCV_ALTERNATIVES_EARLY_BOOT:
|
||||
if (!IS_ENABLED(CONFIG_RISCV_ISA_SVPBMT))
|
||||
return false;
|
||||
default:
|
||||
return riscv_isa_extension_available(NULL, SVPBMT);
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
|
||||
return false;
|
||||
|
||||
return riscv_isa_extension_available(NULL, SVPBMT);
|
||||
}
|
||||
|
||||
static bool __init_or_module cpufeature_probe_zicbom(unsigned int stage)
|
||||
{
|
||||
#ifdef CONFIG_RISCV_ISA_ZICBOM
|
||||
switch (stage) {
|
||||
case RISCV_ALTERNATIVES_EARLY_BOOT:
|
||||
if (!IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM))
|
||||
return false;
|
||||
default:
|
||||
if (riscv_isa_extension_available(NULL, ZICBOM)) {
|
||||
riscv_noncoherent_supported();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
|
||||
return false;
|
||||
|
||||
if (!riscv_isa_extension_available(NULL, ZICBOM))
|
||||
return false;
|
||||
|
||||
riscv_noncoherent_supported();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -297,10 +290,10 @@ static u32 __init_or_module cpufeature_probe(unsigned int stage)
|
||||
u32 cpu_req_feature = 0;
|
||||
|
||||
if (cpufeature_probe_svpbmt(stage))
|
||||
cpu_req_feature |= (1U << CPUFEATURE_SVPBMT);
|
||||
cpu_req_feature |= BIT(CPUFEATURE_SVPBMT);
|
||||
|
||||
if (cpufeature_probe_zicbom(stage))
|
||||
cpu_req_feature |= (1U << CPUFEATURE_ZICBOM);
|
||||
cpu_req_feature |= BIT(CPUFEATURE_ZICBOM);
|
||||
|
||||
return cpu_req_feature;
|
||||
}
|
||||
|
@ -252,10 +252,10 @@ static void __init parse_dtb(void)
|
||||
pr_info("Machine model: %s\n", name);
|
||||
dump_stack_set_arch_desc("%s (DT)", name);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
pr_err("No DTB passed to the kernel\n");
|
||||
}
|
||||
|
||||
pr_err("No DTB passed to the kernel\n");
|
||||
#ifdef CONFIG_CMDLINE_FORCE
|
||||
strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||
pr_info("Forcing kernel command line to: %s\n", boot_command_line);
|
||||
|
@ -18,9 +18,6 @@ static long riscv_sys_mmap(unsigned long addr, unsigned long len,
|
||||
if (unlikely(offset & (~PAGE_MASK >> page_shift_offset)))
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely((prot & PROT_WRITE) && !(prot & PROT_READ)))
|
||||
return -EINVAL;
|
||||
|
||||
return ksys_mmap_pgoff(addr, len, prot, flags, fd,
|
||||
offset >> (PAGE_SHIFT - page_shift_offset));
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ void die(struct pt_regs *regs, const char *str)
|
||||
{
|
||||
static int die_counter;
|
||||
int ret;
|
||||
long cause;
|
||||
|
||||
oops_enter();
|
||||
|
||||
@ -42,11 +43,13 @@ void die(struct pt_regs *regs, const char *str)
|
||||
|
||||
pr_emerg("%s [#%d]\n", str, ++die_counter);
|
||||
print_modules();
|
||||
show_regs(regs);
|
||||
if (regs)
|
||||
show_regs(regs);
|
||||
|
||||
ret = notify_die(DIE_OOPS, str, regs, 0, regs->cause, SIGSEGV);
|
||||
cause = regs ? regs->cause : -1;
|
||||
ret = notify_die(DIE_OOPS, str, regs, 0, cause, SIGSEGV);
|
||||
|
||||
if (regs && kexec_should_crash(current))
|
||||
if (kexec_should_crash(current))
|
||||
crash_kexec(regs);
|
||||
|
||||
bust_spinlocks(0);
|
||||
|
@ -60,6 +60,11 @@ struct __vdso_info {
|
||||
struct vm_special_mapping *cm;
|
||||
};
|
||||
|
||||
static struct __vdso_info vdso_info;
|
||||
#ifdef CONFIG_COMPAT
|
||||
static struct __vdso_info compat_vdso_info;
|
||||
#endif
|
||||
|
||||
static int vdso_mremap(const struct vm_special_mapping *sm,
|
||||
struct vm_area_struct *new_vma)
|
||||
{
|
||||
@ -115,15 +120,18 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
|
||||
struct mm_struct *mm = task->mm;
|
||||
struct vm_area_struct *vma;
|
||||
VMA_ITERATOR(vmi, mm, 0);
|
||||
struct __vdso_info *vdso_info = mm->context.vdso_info;
|
||||
|
||||
mmap_read_lock(mm);
|
||||
|
||||
for_each_vma(vmi, vma) {
|
||||
unsigned long size = vma->vm_end - vma->vm_start;
|
||||
|
||||
if (vma_is_special_mapping(vma, vdso_info->dm))
|
||||
if (vma_is_special_mapping(vma, vdso_info.dm))
|
||||
zap_page_range(vma, vma->vm_start, size);
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (vma_is_special_mapping(vma, compat_vdso_info.dm))
|
||||
zap_page_range(vma, vma->vm_start, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
mmap_read_unlock(mm);
|
||||
@ -265,7 +273,6 @@ static int __setup_additional_pages(struct mm_struct *mm,
|
||||
|
||||
vdso_base += VVAR_SIZE;
|
||||
mm->context.vdso = (void *)vdso_base;
|
||||
mm->context.vdso_info = (void *)vdso_info;
|
||||
|
||||
ret =
|
||||
_install_special_mapping(mm, vdso_base, vdso_text_len,
|
||||
|
@ -184,7 +184,8 @@ static inline bool access_error(unsigned long cause, struct vm_area_struct *vma)
|
||||
}
|
||||
break;
|
||||
case EXC_LOAD_PAGE_FAULT:
|
||||
if (!(vma->vm_flags & VM_READ)) {
|
||||
/* Write implies read */
|
||||
if (!(vma->vm_flags & (VM_READ | VM_WRITE))) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
@ -52,9 +52,6 @@ static unsigned int num_devices = 1;
|
||||
static size_t huge_class_size;
|
||||
|
||||
static const struct block_device_operations zram_devops;
|
||||
#ifdef CONFIG_ZRAM_WRITEBACK
|
||||
static const struct block_device_operations zram_wb_devops;
|
||||
#endif
|
||||
|
||||
static void zram_free_page(struct zram *zram, size_t index);
|
||||
static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
|
||||
@ -546,17 +543,6 @@ static ssize_t backing_dev_store(struct device *dev,
|
||||
zram->backing_dev = backing_dev;
|
||||
zram->bitmap = bitmap;
|
||||
zram->nr_pages = nr_pages;
|
||||
/*
|
||||
* With writeback feature, zram does asynchronous IO so it's no longer
|
||||
* synchronous device so let's remove synchronous io flag. Othewise,
|
||||
* upper layer(e.g., swap) could wait IO completion rather than
|
||||
* (submit and return), which will cause system sluggish.
|
||||
* Furthermore, when the IO function returns(e.g., swap_readpage),
|
||||
* upper layer expects IO was done so it could deallocate the page
|
||||
* freely but in fact, IO is going on so finally could cause
|
||||
* use-after-free when the IO is really done.
|
||||
*/
|
||||
zram->disk->fops = &zram_wb_devops;
|
||||
up_write(&zram->init_lock);
|
||||
|
||||
pr_info("setup backing device %s\n", file_name);
|
||||
@ -1270,6 +1256,9 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
|
||||
struct bio_vec bvec;
|
||||
|
||||
zram_slot_unlock(zram, index);
|
||||
/* A null bio means rw_page was used, we must fallback to bio */
|
||||
if (!bio)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
bvec.bv_page = page;
|
||||
bvec.bv_len = PAGE_SIZE;
|
||||
@ -1856,15 +1845,6 @@ static const struct block_device_operations zram_devops = {
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ZRAM_WRITEBACK
|
||||
static const struct block_device_operations zram_wb_devops = {
|
||||
.open = zram_open,
|
||||
.submit_bio = zram_submit_bio,
|
||||
.swap_slot_free_notify = zram_slot_free_notify,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
#endif
|
||||
|
||||
static DEVICE_ATTR_WO(compact);
|
||||
static DEVICE_ATTR_RW(disksize);
|
||||
static DEVICE_ATTR_RO(initstate);
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk/spear.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk/spear.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
#include "clk.h"
|
||||
|
@ -473,7 +473,7 @@ config EDAC_ALTERA_SDMMC
|
||||
|
||||
config EDAC_SIFIVE
|
||||
bool "Sifive platform EDAC driver"
|
||||
depends on EDAC=y && SIFIVE_L2
|
||||
depends on EDAC=y && SIFIVE_CCACHE
|
||||
help
|
||||
Support for error detection and correction on the SiFive SoCs.
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
/*
|
||||
* SiFive Platform EDAC Driver
|
||||
*
|
||||
* Copyright (C) 2018-2019 SiFive, Inc.
|
||||
* Copyright (C) 2018-2022 SiFive, Inc.
|
||||
*
|
||||
* This driver is partially based on octeon_edac-pc.c
|
||||
*
|
||||
@ -10,7 +10,7 @@
|
||||
#include <linux/edac.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "edac_module.h"
|
||||
#include <soc/sifive/sifive_l2_cache.h>
|
||||
#include <soc/sifive/sifive_ccache.h>
|
||||
|
||||
#define DRVNAME "sifive_edac"
|
||||
|
||||
@ -32,9 +32,9 @@ int ecc_err_event(struct notifier_block *this, unsigned long event, void *ptr)
|
||||
|
||||
p = container_of(this, struct sifive_edac_priv, notifier);
|
||||
|
||||
if (event == SIFIVE_L2_ERR_TYPE_UE)
|
||||
if (event == SIFIVE_CCACHE_ERR_TYPE_UE)
|
||||
edac_device_handle_ue(p->dci, 0, 0, msg);
|
||||
else if (event == SIFIVE_L2_ERR_TYPE_CE)
|
||||
else if (event == SIFIVE_CCACHE_ERR_TYPE_CE)
|
||||
edac_device_handle_ce(p->dci, 0, 0, msg);
|
||||
|
||||
return NOTIFY_OK;
|
||||
@ -67,7 +67,7 @@ static int ecc_register(struct platform_device *pdev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
register_sifive_l2_error_notifier(&p->notifier);
|
||||
register_sifive_ccache_error_notifier(&p->notifier);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -81,7 +81,7 @@ static int ecc_unregister(struct platform_device *pdev)
|
||||
{
|
||||
struct sifive_edac_priv *p = platform_get_drvdata(pdev);
|
||||
|
||||
unregister_sifive_l2_error_notifier(&p->notifier);
|
||||
unregister_sifive_ccache_error_notifier(&p->notifier);
|
||||
edac_device_del_device(&pdev->dev);
|
||||
edac_device_free_ctl_info(p->dci);
|
||||
|
||||
|
@ -223,7 +223,7 @@ svm_migrate_get_vram_page(struct svm_range *prange, unsigned long pfn)
|
||||
page = pfn_to_page(pfn);
|
||||
svm_range_bo_ref(prange->svm_bo);
|
||||
page->zone_device_data = prange->svm_bo;
|
||||
lock_page(page);
|
||||
zone_device_page_init(page);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -410,7 +410,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
uint64_t npages = (end - start) >> PAGE_SHIFT;
|
||||
struct kfd_process_device *pdd;
|
||||
struct dma_fence *mfence = NULL;
|
||||
struct migrate_vma migrate;
|
||||
struct migrate_vma migrate = { 0 };
|
||||
unsigned long cpages = 0;
|
||||
dma_addr_t *scratch;
|
||||
void *buf;
|
||||
@ -666,7 +666,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
static long
|
||||
svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
struct vm_area_struct *vma, uint64_t start, uint64_t end,
|
||||
uint32_t trigger)
|
||||
uint32_t trigger, struct page *fault_page)
|
||||
{
|
||||
struct kfd_process *p = container_of(prange->svms, struct kfd_process, svms);
|
||||
uint64_t npages = (end - start) >> PAGE_SHIFT;
|
||||
@ -674,7 +674,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
unsigned long cpages = 0;
|
||||
struct kfd_process_device *pdd;
|
||||
struct dma_fence *mfence = NULL;
|
||||
struct migrate_vma migrate;
|
||||
struct migrate_vma migrate = { 0 };
|
||||
dma_addr_t *scratch;
|
||||
void *buf;
|
||||
int r = -ENOMEM;
|
||||
@ -697,6 +697,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
|
||||
migrate.src = buf;
|
||||
migrate.dst = migrate.src + npages;
|
||||
migrate.fault_page = fault_page;
|
||||
scratch = (dma_addr_t *)(migrate.dst + npages);
|
||||
|
||||
kfd_smi_event_migration_start(adev->kfd.dev, p->lead_thread->pid,
|
||||
@ -764,7 +765,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
* 0 - OK, otherwise error code
|
||||
*/
|
||||
int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm,
|
||||
uint32_t trigger)
|
||||
uint32_t trigger, struct page *fault_page)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct vm_area_struct *vma;
|
||||
@ -805,7 +806,8 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm,
|
||||
}
|
||||
|
||||
next = min(vma->vm_end, end);
|
||||
r = svm_migrate_vma_to_ram(adev, prange, vma, addr, next, trigger);
|
||||
r = svm_migrate_vma_to_ram(adev, prange, vma, addr, next, trigger,
|
||||
fault_page);
|
||||
if (r < 0) {
|
||||
pr_debug("failed %ld to migrate prange %p\n", r, prange);
|
||||
break;
|
||||
@ -849,7 +851,7 @@ svm_migrate_vram_to_vram(struct svm_range *prange, uint32_t best_loc,
|
||||
pr_debug("from gpu 0x%x to gpu 0x%x\n", prange->actual_loc, best_loc);
|
||||
|
||||
do {
|
||||
r = svm_migrate_vram_to_ram(prange, mm, trigger);
|
||||
r = svm_migrate_vram_to_ram(prange, mm, trigger, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
} while (prange->actual_loc && --retries);
|
||||
@ -950,7 +952,8 @@ static vm_fault_t svm_migrate_to_ram(struct vm_fault *vmf)
|
||||
}
|
||||
|
||||
r = svm_migrate_vram_to_ram(prange, vmf->vma->vm_mm,
|
||||
KFD_MIGRATE_TRIGGER_PAGEFAULT_CPU);
|
||||
KFD_MIGRATE_TRIGGER_PAGEFAULT_CPU,
|
||||
vmf->page);
|
||||
if (r)
|
||||
pr_debug("failed %d migrate svms 0x%p range 0x%p [0x%lx 0x%lx]\n",
|
||||
r, prange->svms, prange, prange->start, prange->last);
|
||||
|
@ -43,7 +43,7 @@ enum MIGRATION_COPY_DIR {
|
||||
int svm_migrate_to_vram(struct svm_range *prange, uint32_t best_loc,
|
||||
struct mm_struct *mm, uint32_t trigger);
|
||||
int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm,
|
||||
uint32_t trigger);
|
||||
uint32_t trigger, struct page *fault_page);
|
||||
unsigned long
|
||||
svm_migrate_addr_to_pfn(struct amdgpu_device *adev, unsigned long addr);
|
||||
|
||||
|
@ -2913,13 +2913,15 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
|
||||
*/
|
||||
if (prange->actual_loc)
|
||||
r = svm_migrate_vram_to_ram(prange, mm,
|
||||
KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU);
|
||||
KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU,
|
||||
NULL);
|
||||
else
|
||||
r = 0;
|
||||
}
|
||||
} else {
|
||||
r = svm_migrate_vram_to_ram(prange, mm,
|
||||
KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU);
|
||||
KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU,
|
||||
NULL);
|
||||
}
|
||||
if (r) {
|
||||
pr_debug("failed %d to migrate svms %p [0x%lx 0x%lx]\n",
|
||||
@ -3278,7 +3280,8 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange,
|
||||
return 0;
|
||||
|
||||
if (!best_loc) {
|
||||
r = svm_migrate_vram_to_ram(prange, mm, KFD_MIGRATE_TRIGGER_PREFETCH);
|
||||
r = svm_migrate_vram_to_ram(prange, mm,
|
||||
KFD_MIGRATE_TRIGGER_PREFETCH, NULL);
|
||||
*migrated = !r;
|
||||
return r;
|
||||
}
|
||||
@ -3339,7 +3342,7 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work)
|
||||
mutex_lock(&prange->migrate_mutex);
|
||||
do {
|
||||
r = svm_migrate_vram_to_ram(prange, mm,
|
||||
KFD_MIGRATE_TRIGGER_TTM_EVICTION);
|
||||
KFD_MIGRATE_TRIGGER_TTM_EVICTION, NULL);
|
||||
} while (!r && prange->actual_loc && --retries);
|
||||
|
||||
if (!r && prange->actual_loc)
|
||||
|
@ -8310,8 +8310,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
crtc, dm_new_crtc_state, cur_crc_src))
|
||||
DRM_DEBUG_DRIVER("Failed to configure crc source");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, j)
|
||||
|
@ -139,44 +139,24 @@ static void nouveau_dmem_fence_done(struct nouveau_fence **fence)
|
||||
}
|
||||
}
|
||||
|
||||
static vm_fault_t nouveau_dmem_fault_copy_one(struct nouveau_drm *drm,
|
||||
struct vm_fault *vmf, struct migrate_vma *args,
|
||||
dma_addr_t *dma_addr)
|
||||
static int nouveau_dmem_copy_one(struct nouveau_drm *drm, struct page *spage,
|
||||
struct page *dpage, dma_addr_t *dma_addr)
|
||||
{
|
||||
struct device *dev = drm->dev->dev;
|
||||
struct page *dpage, *spage;
|
||||
struct nouveau_svmm *svmm;
|
||||
|
||||
spage = migrate_pfn_to_page(args->src[0]);
|
||||
if (!spage || !(args->src[0] & MIGRATE_PFN_MIGRATE))
|
||||
return 0;
|
||||
|
||||
dpage = alloc_page_vma(GFP_HIGHUSER, vmf->vma, vmf->address);
|
||||
if (!dpage)
|
||||
return VM_FAULT_SIGBUS;
|
||||
lock_page(dpage);
|
||||
|
||||
*dma_addr = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(dev, *dma_addr))
|
||||
goto error_free_page;
|
||||
return -EIO;
|
||||
|
||||
svmm = spage->zone_device_data;
|
||||
mutex_lock(&svmm->mutex);
|
||||
nouveau_svmm_invalidate(svmm, args->start, args->end);
|
||||
if (drm->dmem->migrate.copy_func(drm, 1, NOUVEAU_APER_HOST, *dma_addr,
|
||||
NOUVEAU_APER_VRAM, nouveau_dmem_page_addr(spage)))
|
||||
goto error_dma_unmap;
|
||||
mutex_unlock(&svmm->mutex);
|
||||
NOUVEAU_APER_VRAM, nouveau_dmem_page_addr(spage))) {
|
||||
dma_unmap_page(dev, *dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
args->dst[0] = migrate_pfn(page_to_pfn(dpage));
|
||||
return 0;
|
||||
|
||||
error_dma_unmap:
|
||||
mutex_unlock(&svmm->mutex);
|
||||
dma_unmap_page(dev, *dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
|
||||
error_free_page:
|
||||
__free_page(dpage);
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf)
|
||||
@ -184,9 +164,11 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf)
|
||||
struct nouveau_drm *drm = page_to_drm(vmf->page);
|
||||
struct nouveau_dmem *dmem = drm->dmem;
|
||||
struct nouveau_fence *fence;
|
||||
struct nouveau_svmm *svmm;
|
||||
struct page *spage, *dpage;
|
||||
unsigned long src = 0, dst = 0;
|
||||
dma_addr_t dma_addr = 0;
|
||||
vm_fault_t ret;
|
||||
vm_fault_t ret = 0;
|
||||
struct migrate_vma args = {
|
||||
.vma = vmf->vma,
|
||||
.start = vmf->address,
|
||||
@ -207,10 +189,26 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf)
|
||||
if (!args.cpages)
|
||||
return 0;
|
||||
|
||||
ret = nouveau_dmem_fault_copy_one(drm, vmf, &args, &dma_addr);
|
||||
if (ret || dst == 0)
|
||||
spage = migrate_pfn_to_page(src);
|
||||
if (!spage || !(src & MIGRATE_PFN_MIGRATE))
|
||||
goto done;
|
||||
|
||||
dpage = alloc_page_vma(GFP_HIGHUSER, vmf->vma, vmf->address);
|
||||
if (!dpage)
|
||||
goto done;
|
||||
|
||||
dst = migrate_pfn(page_to_pfn(dpage));
|
||||
|
||||
svmm = spage->zone_device_data;
|
||||
mutex_lock(&svmm->mutex);
|
||||
nouveau_svmm_invalidate(svmm, args.start, args.end);
|
||||
ret = nouveau_dmem_copy_one(drm, spage, dpage, &dma_addr);
|
||||
mutex_unlock(&svmm->mutex);
|
||||
if (ret) {
|
||||
ret = VM_FAULT_SIGBUS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
nouveau_fence_new(dmem->migrate.chan, false, &fence);
|
||||
migrate_vma_pages(&args);
|
||||
nouveau_dmem_fence_done(&fence);
|
||||
@ -326,7 +324,7 @@ nouveau_dmem_page_alloc_locked(struct nouveau_drm *drm)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lock_page(page);
|
||||
zone_device_page_init(page);
|
||||
return page;
|
||||
}
|
||||
|
||||
@ -369,6 +367,52 @@ nouveau_dmem_suspend(struct nouveau_drm *drm)
|
||||
mutex_unlock(&drm->dmem->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Evict all pages mapping a chunk.
|
||||
*/
|
||||
static void
|
||||
nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk)
|
||||
{
|
||||
unsigned long i, npages = range_len(&chunk->pagemap.range) >> PAGE_SHIFT;
|
||||
unsigned long *src_pfns, *dst_pfns;
|
||||
dma_addr_t *dma_addrs;
|
||||
struct nouveau_fence *fence;
|
||||
|
||||
src_pfns = kcalloc(npages, sizeof(*src_pfns), GFP_KERNEL);
|
||||
dst_pfns = kcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL);
|
||||
dma_addrs = kcalloc(npages, sizeof(*dma_addrs), GFP_KERNEL);
|
||||
|
||||
migrate_device_range(src_pfns, chunk->pagemap.range.start >> PAGE_SHIFT,
|
||||
npages);
|
||||
|
||||
for (i = 0; i < npages; i++) {
|
||||
if (src_pfns[i] & MIGRATE_PFN_MIGRATE) {
|
||||
struct page *dpage;
|
||||
|
||||
/*
|
||||
* _GFP_NOFAIL because the GPU is going away and there
|
||||
* is nothing sensible we can do if we can't copy the
|
||||
* data back.
|
||||
*/
|
||||
dpage = alloc_page(GFP_HIGHUSER | __GFP_NOFAIL);
|
||||
dst_pfns[i] = migrate_pfn(page_to_pfn(dpage));
|
||||
nouveau_dmem_copy_one(chunk->drm,
|
||||
migrate_pfn_to_page(src_pfns[i]), dpage,
|
||||
&dma_addrs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
nouveau_fence_new(chunk->drm->dmem->migrate.chan, false, &fence);
|
||||
migrate_device_pages(src_pfns, dst_pfns, npages);
|
||||
nouveau_dmem_fence_done(&fence);
|
||||
migrate_device_finalize(src_pfns, dst_pfns, npages);
|
||||
kfree(src_pfns);
|
||||
kfree(dst_pfns);
|
||||
for (i = 0; i < npages; i++)
|
||||
dma_unmap_page(chunk->drm->dev->dev, dma_addrs[i], PAGE_SIZE, DMA_BIDIRECTIONAL);
|
||||
kfree(dma_addrs);
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_dmem_fini(struct nouveau_drm *drm)
|
||||
{
|
||||
@ -380,8 +424,10 @@ nouveau_dmem_fini(struct nouveau_drm *drm)
|
||||
mutex_lock(&drm->dmem->mutex);
|
||||
|
||||
list_for_each_entry_safe(chunk, tmp, &drm->dmem->chunks, list) {
|
||||
nouveau_dmem_evict_chunk(chunk);
|
||||
nouveau_bo_unpin(chunk->bo);
|
||||
nouveau_bo_ref(NULL, &chunk->bo);
|
||||
WARN_ON(chunk->callocated);
|
||||
list_del(&chunk->list);
|
||||
memunmap_pages(&chunk->pagemap);
|
||||
release_mem_region(chunk->pagemap.range.start,
|
||||
|
@ -101,6 +101,7 @@ struct pca963x_led {
|
||||
struct pca963x *chip;
|
||||
struct led_classdev led_cdev;
|
||||
int led_num; /* 0 .. 15 potentially */
|
||||
bool blinking;
|
||||
u8 gdc;
|
||||
u8 gfrq;
|
||||
};
|
||||
@ -129,12 +130,21 @@ static int pca963x_brightness(struct pca963x_led *led,
|
||||
|
||||
switch (brightness) {
|
||||
case LED_FULL:
|
||||
val = (ledout & ~mask) | (PCA963X_LED_ON << shift);
|
||||
if (led->blinking) {
|
||||
val = (ledout & ~mask) | (PCA963X_LED_GRP_PWM << shift);
|
||||
ret = i2c_smbus_write_byte_data(client,
|
||||
PCA963X_PWM_BASE +
|
||||
led->led_num,
|
||||
LED_FULL);
|
||||
} else {
|
||||
val = (ledout & ~mask) | (PCA963X_LED_ON << shift);
|
||||
}
|
||||
ret = i2c_smbus_write_byte_data(client, ledout_addr, val);
|
||||
break;
|
||||
case LED_OFF:
|
||||
val = ledout & ~mask;
|
||||
ret = i2c_smbus_write_byte_data(client, ledout_addr, val);
|
||||
led->blinking = false;
|
||||
break;
|
||||
default:
|
||||
ret = i2c_smbus_write_byte_data(client,
|
||||
@ -144,7 +154,11 @@ static int pca963x_brightness(struct pca963x_led *led,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = (ledout & ~mask) | (PCA963X_LED_PWM << shift);
|
||||
if (led->blinking)
|
||||
val = (ledout & ~mask) | (PCA963X_LED_GRP_PWM << shift);
|
||||
else
|
||||
val = (ledout & ~mask) | (PCA963X_LED_PWM << shift);
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, ledout_addr, val);
|
||||
break;
|
||||
}
|
||||
@ -181,6 +195,7 @@ static void pca963x_blink(struct pca963x_led *led)
|
||||
}
|
||||
|
||||
mutex_unlock(&led->chip->mutex);
|
||||
led->blinking = true;
|
||||
}
|
||||
|
||||
static int pca963x_power_state(struct pca963x_led *led)
|
||||
@ -275,6 +290,8 @@ static int pca963x_blink_set(struct led_classdev *led_cdev,
|
||||
led->gfrq = gfrq;
|
||||
|
||||
pca963x_blink(led);
|
||||
led->led_cdev.brightness = LED_FULL;
|
||||
pca963x_led_set(led_cdev, LED_FULL);
|
||||
|
||||
*delay_on = time_on;
|
||||
*delay_off = time_off;
|
||||
@ -337,6 +354,7 @@ static int pca963x_register_leds(struct i2c_client *client,
|
||||
led->led_cdev.brightness_set_blocking = pca963x_led_set;
|
||||
if (hw_blink)
|
||||
led->led_cdev.blink_set = pca963x_blink_set;
|
||||
led->blinking = false;
|
||||
|
||||
init_data.fwnode = child;
|
||||
/* for backwards compatibility */
|
||||
|
@ -393,7 +393,7 @@ static int parse_slot_config(int slot,
|
||||
}
|
||||
|
||||
if (p0 + function_len < pos) {
|
||||
printk(KERN_ERR "eisa_enumerator: function %d length mis-match "
|
||||
printk(KERN_ERR "eisa_enumerator: function %d length mismatch "
|
||||
"got %d, expected %d\n",
|
||||
num_func, pos-p0, function_len);
|
||||
res=-1;
|
||||
@ -407,13 +407,13 @@ static int parse_slot_config(int slot,
|
||||
}
|
||||
|
||||
if (pos != es->config_data_length) {
|
||||
printk(KERN_ERR "eisa_enumerator: config data length mis-match got %d, expected %d\n",
|
||||
printk(KERN_ERR "eisa_enumerator: config data length mismatch got %d, expected %d\n",
|
||||
pos, es->config_data_length);
|
||||
res=-1;
|
||||
}
|
||||
|
||||
if (num_func != es->num_functions) {
|
||||
printk(KERN_ERR "eisa_enumerator: number of functions mis-match got %d, expected %d\n",
|
||||
printk(KERN_ERR "eisa_enumerator: number of functions mismatch got %d, expected %d\n",
|
||||
num_func, es->num_functions);
|
||||
res=-2;
|
||||
}
|
||||
@ -451,7 +451,7 @@ static int init_slot(int slot, struct eeprom_eisa_slot_info *es)
|
||||
}
|
||||
if (es->eisa_slot_id != id) {
|
||||
print_eisa_id(id_string, id);
|
||||
printk(KERN_ERR "EISA slot %d id mis-match: got %s",
|
||||
printk(KERN_ERR "EISA slot %d id mismatch: got %s",
|
||||
slot, id_string);
|
||||
|
||||
print_eisa_id(id_string, es->eisa_slot_id);
|
||||
|
@ -185,7 +185,7 @@ config APPLE_M1_CPU_PMU
|
||||
|
||||
config ALIBABA_UNCORE_DRW_PMU
|
||||
tristate "Alibaba T-Head Yitian 710 DDR Sub-system Driveway PMU driver"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
depends on (ARM64 && ACPI) || COMPILE_TEST
|
||||
help
|
||||
Support for Driveway PMU events monitoring on Yitian 710 DDR
|
||||
Sub-system.
|
||||
|
@ -658,8 +658,8 @@ static int ali_drw_pmu_probe(struct platform_device *pdev)
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
drw_pmu->cfg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (!drw_pmu->cfg_base)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(drw_pmu->cfg_base))
|
||||
return PTR_ERR(drw_pmu->cfg_base);
|
||||
|
||||
name = devm_kasprintf(drw_pmu->dev, GFP_KERNEL, "ali_drw_%llx",
|
||||
(u64) (res->start >> ALI_DRW_PMU_PA_SHIFT));
|
||||
|
@ -652,8 +652,11 @@ static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node)
|
||||
struct riscv_pmu *pmu = hlist_entry_safe(node, struct riscv_pmu, node);
|
||||
struct cpu_hw_events *cpu_hw_evt = this_cpu_ptr(pmu->hw_events);
|
||||
|
||||
/* Enable the access for TIME csr only from the user mode now */
|
||||
csr_write(CSR_SCOUNTEREN, 0x2);
|
||||
/*
|
||||
* Enable the access for CYCLE, TIME, and INSTRET CSRs from userspace,
|
||||
* as is necessary to maintain uABI compatibility.
|
||||
*/
|
||||
csr_write(CSR_SCOUNTEREN, 0x7);
|
||||
|
||||
/* Stop all the counters so that they can be enabled from perf */
|
||||
pmu_sbi_stop_all(pmu);
|
||||
|
@ -15,12 +15,14 @@
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kobject.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/cio.h>
|
||||
#include <asm/ccwdev.h>
|
||||
#include <asm/debug.h>
|
||||
#include <asm/diag.h>
|
||||
#include <asm/scsw.h>
|
||||
|
||||
#include "vmur.h"
|
||||
|
||||
@ -78,6 +80,8 @@ static struct ccw_driver ur_driver = {
|
||||
|
||||
static DEFINE_MUTEX(vmur_mutex);
|
||||
|
||||
static void ur_uevent(struct work_struct *ws);
|
||||
|
||||
/*
|
||||
* Allocation, freeing, getting and putting of urdev structures
|
||||
*
|
||||
@ -108,6 +112,7 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
|
||||
ccw_device_get_id(cdev, &urd->dev_id);
|
||||
mutex_init(&urd->io_mutex);
|
||||
init_waitqueue_head(&urd->wait);
|
||||
INIT_WORK(&urd->uevent_work, ur_uevent);
|
||||
spin_lock_init(&urd->open_lock);
|
||||
refcount_set(&urd->ref_count, 1);
|
||||
urd->cdev = cdev;
|
||||
@ -275,6 +280,18 @@ static int do_ur_io(struct urdev *urd, struct ccw1 *cpa)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void ur_uevent(struct work_struct *ws)
|
||||
{
|
||||
struct urdev *urd = container_of(ws, struct urdev, uevent_work);
|
||||
char *envp[] = {
|
||||
"EVENT=unsol_de", /* Unsolicited device-end interrupt */
|
||||
NULL
|
||||
};
|
||||
|
||||
kobject_uevent_env(&urd->cdev->dev.kobj, KOBJ_CHANGE, envp);
|
||||
urdev_put(urd);
|
||||
}
|
||||
|
||||
/*
|
||||
* ur interrupt handler, called from the ccw_device layer
|
||||
*/
|
||||
@ -288,12 +305,21 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
||||
intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
|
||||
irb->scsw.cmd.count);
|
||||
}
|
||||
urd = dev_get_drvdata(&cdev->dev);
|
||||
if (!intparm) {
|
||||
TRACE("ur_int_handler: unsolicited interrupt\n");
|
||||
|
||||
if (scsw_dstat(&irb->scsw) & DEV_STAT_DEV_END) {
|
||||
/*
|
||||
* Userspace might be interested in a transition to
|
||||
* device-ready state.
|
||||
*/
|
||||
urdev_get(urd);
|
||||
schedule_work(&urd->uevent_work);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
urd = dev_get_drvdata(&cdev->dev);
|
||||
BUG_ON(!urd);
|
||||
/* On special conditions irb is an error pointer */
|
||||
if (IS_ERR(irb))
|
||||
urd->io_request_rc = PTR_ERR(irb);
|
||||
@ -809,7 +835,6 @@ static int ur_probe(struct ccw_device *cdev)
|
||||
rc = -ENOMEM;
|
||||
goto fail_urdev_put;
|
||||
}
|
||||
cdev->handler = ur_int_handler;
|
||||
|
||||
/* validate virtual unit record device */
|
||||
urd->class = get_urd_class(urd);
|
||||
@ -823,6 +848,7 @@ static int ur_probe(struct ccw_device *cdev)
|
||||
}
|
||||
spin_lock_irq(get_ccwdev_lock(cdev));
|
||||
dev_set_drvdata(&cdev->dev, urd);
|
||||
cdev->handler = ur_int_handler;
|
||||
spin_unlock_irq(get_ccwdev_lock(cdev));
|
||||
|
||||
mutex_unlock(&vmur_mutex);
|
||||
@ -928,6 +954,10 @@ static int ur_set_offline_force(struct ccw_device *cdev, int force)
|
||||
rc = -EBUSY;
|
||||
goto fail_urdev_put;
|
||||
}
|
||||
if (cancel_work_sync(&urd->uevent_work)) {
|
||||
/* Work not run yet - need to release reference here */
|
||||
urdev_put(urd);
|
||||
}
|
||||
device_destroy(vmur_class, urd->char_device->dev);
|
||||
cdev_del(urd->char_device);
|
||||
urd->char_device = NULL;
|
||||
@ -963,6 +993,7 @@ static void ur_remove(struct ccw_device *cdev)
|
||||
spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
|
||||
urdev_put(dev_get_drvdata(&cdev->dev));
|
||||
dev_set_drvdata(&cdev->dev, NULL);
|
||||
cdev->handler = NULL;
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
|
||||
|
||||
mutex_unlock(&vmur_mutex);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#define _VMUR_H_
|
||||
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define DEV_CLASS_UR_I 0x20 /* diag210 unit record input device class */
|
||||
#define DEV_CLASS_UR_O 0x10 /* diag210 unit record output device class */
|
||||
@ -76,6 +77,7 @@ struct urdev {
|
||||
wait_queue_head_t wait; /* wait queue to serialize open */
|
||||
int open_flag; /* "urdev is open" flag */
|
||||
spinlock_t open_lock; /* serialize critical sections */
|
||||
struct work_struct uevent_work; /* work to send uevent */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
if SOC_SIFIVE
|
||||
|
||||
config SIFIVE_L2
|
||||
bool "Sifive L2 Cache controller"
|
||||
config SIFIVE_CCACHE
|
||||
bool "Sifive Composable Cache controller"
|
||||
help
|
||||
Support for the L2 cache controller on SiFive platforms.
|
||||
Support for the composable cache controller on SiFive platforms.
|
||||
|
||||
endif
|
||||
|
@ -1,3 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_SIFIVE_L2) += sifive_l2_cache.o
|
||||
obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
|
||||
|
255
drivers/soc/sifive/sifive_ccache.c
Normal file
255
drivers/soc/sifive/sifive_ccache.c
Normal file
@ -0,0 +1,255 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* SiFive composable cache controller Driver
|
||||
*
|
||||
* Copyright (C) 2018-2022 SiFive, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "CCACHE: " fmt
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <asm/cacheinfo.h>
|
||||
#include <soc/sifive/sifive_ccache.h>
|
||||
|
||||
#define SIFIVE_CCACHE_DIRECCFIX_LOW 0x100
|
||||
#define SIFIVE_CCACHE_DIRECCFIX_HIGH 0x104
|
||||
#define SIFIVE_CCACHE_DIRECCFIX_COUNT 0x108
|
||||
|
||||
#define SIFIVE_CCACHE_DIRECCFAIL_LOW 0x120
|
||||
#define SIFIVE_CCACHE_DIRECCFAIL_HIGH 0x124
|
||||
#define SIFIVE_CCACHE_DIRECCFAIL_COUNT 0x128
|
||||
|
||||
#define SIFIVE_CCACHE_DATECCFIX_LOW 0x140
|
||||
#define SIFIVE_CCACHE_DATECCFIX_HIGH 0x144
|
||||
#define SIFIVE_CCACHE_DATECCFIX_COUNT 0x148
|
||||
|
||||
#define SIFIVE_CCACHE_DATECCFAIL_LOW 0x160
|
||||
#define SIFIVE_CCACHE_DATECCFAIL_HIGH 0x164
|
||||
#define SIFIVE_CCACHE_DATECCFAIL_COUNT 0x168
|
||||
|
||||
#define SIFIVE_CCACHE_CONFIG 0x00
|
||||
#define SIFIVE_CCACHE_CONFIG_BANK_MASK GENMASK_ULL(7, 0)
|
||||
#define SIFIVE_CCACHE_CONFIG_WAYS_MASK GENMASK_ULL(15, 8)
|
||||
#define SIFIVE_CCACHE_CONFIG_SETS_MASK GENMASK_ULL(23, 16)
|
||||
#define SIFIVE_CCACHE_CONFIG_BLKS_MASK GENMASK_ULL(31, 24)
|
||||
|
||||
#define SIFIVE_CCACHE_WAYENABLE 0x08
|
||||
#define SIFIVE_CCACHE_ECCINJECTERR 0x40
|
||||
|
||||
#define SIFIVE_CCACHE_MAX_ECCINTR 4
|
||||
|
||||
static void __iomem *ccache_base;
|
||||
static int g_irq[SIFIVE_CCACHE_MAX_ECCINTR];
|
||||
static struct riscv_cacheinfo_ops ccache_cache_ops;
|
||||
static int level;
|
||||
|
||||
enum {
|
||||
DIR_CORR = 0,
|
||||
DATA_CORR,
|
||||
DATA_UNCORR,
|
||||
DIR_UNCORR,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static struct dentry *sifive_test;
|
||||
|
||||
static ssize_t ccache_write(struct file *file, const char __user *data,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
if (kstrtouint_from_user(data, count, 0, &val))
|
||||
return -EINVAL;
|
||||
if ((val < 0xFF) || (val >= 0x10000 && val < 0x100FF))
|
||||
writel(val, ccache_base + SIFIVE_CCACHE_ECCINJECTERR);
|
||||
else
|
||||
return -EINVAL;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations ccache_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.write = ccache_write
|
||||
};
|
||||
|
||||
static void setup_sifive_debug(void)
|
||||
{
|
||||
sifive_test = debugfs_create_dir("sifive_ccache_cache", NULL);
|
||||
|
||||
debugfs_create_file("sifive_debug_inject_error", 0200,
|
||||
sifive_test, NULL, &ccache_fops);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ccache_config_read(void)
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
cfg = readl(ccache_base + SIFIVE_CCACHE_CONFIG);
|
||||
pr_info("%llu banks, %llu ways, sets/bank=%llu, bytes/block=%llu\n",
|
||||
FIELD_GET(SIFIVE_CCACHE_CONFIG_BANK_MASK, cfg),
|
||||
FIELD_GET(SIFIVE_CCACHE_CONFIG_WAYS_MASK, cfg),
|
||||
BIT_ULL(FIELD_GET(SIFIVE_CCACHE_CONFIG_SETS_MASK, cfg)),
|
||||
BIT_ULL(FIELD_GET(SIFIVE_CCACHE_CONFIG_BLKS_MASK, cfg)));
|
||||
|
||||
cfg = readl(ccache_base + SIFIVE_CCACHE_WAYENABLE);
|
||||
pr_info("Index of the largest way enabled: %u\n", cfg);
|
||||
}
|
||||
|
||||
static const struct of_device_id sifive_ccache_ids[] = {
|
||||
{ .compatible = "sifive,fu540-c000-ccache" },
|
||||
{ .compatible = "sifive,fu740-c000-ccache" },
|
||||
{ .compatible = "sifive,ccache0" },
|
||||
{ /* end of table */ }
|
||||
};
|
||||
|
||||
static ATOMIC_NOTIFIER_HEAD(ccache_err_chain);
|
||||
|
||||
int register_sifive_ccache_error_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_register(&ccache_err_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_sifive_ccache_error_notifier);
|
||||
|
||||
int unregister_sifive_ccache_error_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_unregister(&ccache_err_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_sifive_ccache_error_notifier);
|
||||
|
||||
static int ccache_largest_wayenabled(void)
|
||||
{
|
||||
return readl(ccache_base + SIFIVE_CCACHE_WAYENABLE) & 0xFF;
|
||||
}
|
||||
|
||||
static ssize_t number_of_ways_enabled_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", ccache_largest_wayenabled());
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(number_of_ways_enabled);
|
||||
|
||||
static struct attribute *priv_attrs[] = {
|
||||
&dev_attr_number_of_ways_enabled.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group priv_attr_group = {
|
||||
.attrs = priv_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *ccache_get_priv_group(struct cacheinfo
|
||||
*this_leaf)
|
||||
{
|
||||
/* We want to use private group for composable cache only */
|
||||
if (this_leaf->level == level)
|
||||
return &priv_attr_group;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static irqreturn_t ccache_int_handler(int irq, void *device)
|
||||
{
|
||||
unsigned int add_h, add_l;
|
||||
|
||||
if (irq == g_irq[DIR_CORR]) {
|
||||
add_h = readl(ccache_base + SIFIVE_CCACHE_DIRECCFIX_HIGH);
|
||||
add_l = readl(ccache_base + SIFIVE_CCACHE_DIRECCFIX_LOW);
|
||||
pr_err("DirError @ 0x%08X.%08X\n", add_h, add_l);
|
||||
/* Reading this register clears the DirError interrupt sig */
|
||||
readl(ccache_base + SIFIVE_CCACHE_DIRECCFIX_COUNT);
|
||||
atomic_notifier_call_chain(&ccache_err_chain,
|
||||
SIFIVE_CCACHE_ERR_TYPE_CE,
|
||||
"DirECCFix");
|
||||
}
|
||||
if (irq == g_irq[DIR_UNCORR]) {
|
||||
add_h = readl(ccache_base + SIFIVE_CCACHE_DIRECCFAIL_HIGH);
|
||||
add_l = readl(ccache_base + SIFIVE_CCACHE_DIRECCFAIL_LOW);
|
||||
/* Reading this register clears the DirFail interrupt sig */
|
||||
readl(ccache_base + SIFIVE_CCACHE_DIRECCFAIL_COUNT);
|
||||
atomic_notifier_call_chain(&ccache_err_chain,
|
||||
SIFIVE_CCACHE_ERR_TYPE_UE,
|
||||
"DirECCFail");
|
||||
panic("CCACHE: DirFail @ 0x%08X.%08X\n", add_h, add_l);
|
||||
}
|
||||
if (irq == g_irq[DATA_CORR]) {
|
||||
add_h = readl(ccache_base + SIFIVE_CCACHE_DATECCFIX_HIGH);
|
||||
add_l = readl(ccache_base + SIFIVE_CCACHE_DATECCFIX_LOW);
|
||||
pr_err("DataError @ 0x%08X.%08X\n", add_h, add_l);
|
||||
/* Reading this register clears the DataError interrupt sig */
|
||||
readl(ccache_base + SIFIVE_CCACHE_DATECCFIX_COUNT);
|
||||
atomic_notifier_call_chain(&ccache_err_chain,
|
||||
SIFIVE_CCACHE_ERR_TYPE_CE,
|
||||
"DatECCFix");
|
||||
}
|
||||
if (irq == g_irq[DATA_UNCORR]) {
|
||||
add_h = readl(ccache_base + SIFIVE_CCACHE_DATECCFAIL_HIGH);
|
||||
add_l = readl(ccache_base + SIFIVE_CCACHE_DATECCFAIL_LOW);
|
||||
pr_err("DataFail @ 0x%08X.%08X\n", add_h, add_l);
|
||||
/* Reading this register clears the DataFail interrupt sig */
|
||||
readl(ccache_base + SIFIVE_CCACHE_DATECCFAIL_COUNT);
|
||||
atomic_notifier_call_chain(&ccache_err_chain,
|
||||
SIFIVE_CCACHE_ERR_TYPE_UE,
|
||||
"DatECCFail");
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __init sifive_ccache_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
int i, rc, intr_num;
|
||||
|
||||
np = of_find_matching_node(NULL, sifive_ccache_ids);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
if (of_address_to_resource(np, 0, &res))
|
||||
return -ENODEV;
|
||||
|
||||
ccache_base = ioremap(res.start, resource_size(&res));
|
||||
if (!ccache_base)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_property_read_u32(np, "cache-level", &level))
|
||||
return -ENOENT;
|
||||
|
||||
intr_num = of_property_count_u32_elems(np, "interrupts");
|
||||
if (!intr_num) {
|
||||
pr_err("No interrupts property\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (i = 0; i < intr_num; i++) {
|
||||
g_irq[i] = irq_of_parse_and_map(np, i);
|
||||
rc = request_irq(g_irq[i], ccache_int_handler, 0, "ccache_ecc",
|
||||
NULL);
|
||||
if (rc) {
|
||||
pr_err("Could not request IRQ %d\n", g_irq[i]);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
ccache_config_read();
|
||||
|
||||
ccache_cache_ops.get_priv_group = ccache_get_priv_group;
|
||||
riscv_set_cacheinfo_ops(&ccache_cache_ops);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
setup_sifive_debug();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(sifive_ccache_init);
|
@ -1,237 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* SiFive L2 cache controller Driver
|
||||
*
|
||||
* Copyright (C) 2018-2019 SiFive, Inc.
|
||||
*
|
||||
*/
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/device.h>
|
||||
#include <asm/cacheinfo.h>
|
||||
#include <soc/sifive/sifive_l2_cache.h>
|
||||
|
||||
#define SIFIVE_L2_DIRECCFIX_LOW 0x100
|
||||
#define SIFIVE_L2_DIRECCFIX_HIGH 0x104
|
||||
#define SIFIVE_L2_DIRECCFIX_COUNT 0x108
|
||||
|
||||
#define SIFIVE_L2_DIRECCFAIL_LOW 0x120
|
||||
#define SIFIVE_L2_DIRECCFAIL_HIGH 0x124
|
||||
#define SIFIVE_L2_DIRECCFAIL_COUNT 0x128
|
||||
|
||||
#define SIFIVE_L2_DATECCFIX_LOW 0x140
|
||||
#define SIFIVE_L2_DATECCFIX_HIGH 0x144
|
||||
#define SIFIVE_L2_DATECCFIX_COUNT 0x148
|
||||
|
||||
#define SIFIVE_L2_DATECCFAIL_LOW 0x160
|
||||
#define SIFIVE_L2_DATECCFAIL_HIGH 0x164
|
||||
#define SIFIVE_L2_DATECCFAIL_COUNT 0x168
|
||||
|
||||
#define SIFIVE_L2_CONFIG 0x00
|
||||
#define SIFIVE_L2_WAYENABLE 0x08
|
||||
#define SIFIVE_L2_ECCINJECTERR 0x40
|
||||
|
||||
#define SIFIVE_L2_MAX_ECCINTR 4
|
||||
|
||||
static void __iomem *l2_base;
|
||||
static int g_irq[SIFIVE_L2_MAX_ECCINTR];
|
||||
static struct riscv_cacheinfo_ops l2_cache_ops;
|
||||
|
||||
enum {
|
||||
DIR_CORR = 0,
|
||||
DATA_CORR,
|
||||
DATA_UNCORR,
|
||||
DIR_UNCORR,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static struct dentry *sifive_test;
|
||||
|
||||
static ssize_t l2_write(struct file *file, const char __user *data,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
if (kstrtouint_from_user(data, count, 0, &val))
|
||||
return -EINVAL;
|
||||
if ((val < 0xFF) || (val >= 0x10000 && val < 0x100FF))
|
||||
writel(val, l2_base + SIFIVE_L2_ECCINJECTERR);
|
||||
else
|
||||
return -EINVAL;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations l2_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.write = l2_write
|
||||
};
|
||||
|
||||
static void setup_sifive_debug(void)
|
||||
{
|
||||
sifive_test = debugfs_create_dir("sifive_l2_cache", NULL);
|
||||
|
||||
debugfs_create_file("sifive_debug_inject_error", 0200,
|
||||
sifive_test, NULL, &l2_fops);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void l2_config_read(void)
|
||||
{
|
||||
u32 regval, val;
|
||||
|
||||
regval = readl(l2_base + SIFIVE_L2_CONFIG);
|
||||
val = regval & 0xFF;
|
||||
pr_info("L2CACHE: No. of Banks in the cache: %d\n", val);
|
||||
val = (regval & 0xFF00) >> 8;
|
||||
pr_info("L2CACHE: No. of ways per bank: %d\n", val);
|
||||
val = (regval & 0xFF0000) >> 16;
|
||||
pr_info("L2CACHE: Sets per bank: %llu\n", (uint64_t)1 << val);
|
||||
val = (regval & 0xFF000000) >> 24;
|
||||
pr_info("L2CACHE: Bytes per cache block: %llu\n", (uint64_t)1 << val);
|
||||
|
||||
regval = readl(l2_base + SIFIVE_L2_WAYENABLE);
|
||||
pr_info("L2CACHE: Index of the largest way enabled: %d\n", regval);
|
||||
}
|
||||
|
||||
static const struct of_device_id sifive_l2_ids[] = {
|
||||
{ .compatible = "sifive,fu540-c000-ccache" },
|
||||
{ .compatible = "sifive,fu740-c000-ccache" },
|
||||
{ /* end of table */ },
|
||||
};
|
||||
|
||||
static ATOMIC_NOTIFIER_HEAD(l2_err_chain);
|
||||
|
||||
int register_sifive_l2_error_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_register(&l2_err_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_sifive_l2_error_notifier);
|
||||
|
||||
int unregister_sifive_l2_error_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_unregister(&l2_err_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_sifive_l2_error_notifier);
|
||||
|
||||
static int l2_largest_wayenabled(void)
|
||||
{
|
||||
return readl(l2_base + SIFIVE_L2_WAYENABLE) & 0xFF;
|
||||
}
|
||||
|
||||
static ssize_t number_of_ways_enabled_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", l2_largest_wayenabled());
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(number_of_ways_enabled);
|
||||
|
||||
static struct attribute *priv_attrs[] = {
|
||||
&dev_attr_number_of_ways_enabled.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group priv_attr_group = {
|
||||
.attrs = priv_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *l2_get_priv_group(struct cacheinfo *this_leaf)
|
||||
{
|
||||
/* We want to use private group for L2 cache only */
|
||||
if (this_leaf->level == 2)
|
||||
return &priv_attr_group;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static irqreturn_t l2_int_handler(int irq, void *device)
|
||||
{
|
||||
unsigned int add_h, add_l;
|
||||
|
||||
if (irq == g_irq[DIR_CORR]) {
|
||||
add_h = readl(l2_base + SIFIVE_L2_DIRECCFIX_HIGH);
|
||||
add_l = readl(l2_base + SIFIVE_L2_DIRECCFIX_LOW);
|
||||
pr_err("L2CACHE: DirError @ 0x%08X.%08X\n", add_h, add_l);
|
||||
/* Reading this register clears the DirError interrupt sig */
|
||||
readl(l2_base + SIFIVE_L2_DIRECCFIX_COUNT);
|
||||
atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE,
|
||||
"DirECCFix");
|
||||
}
|
||||
if (irq == g_irq[DIR_UNCORR]) {
|
||||
add_h = readl(l2_base + SIFIVE_L2_DIRECCFAIL_HIGH);
|
||||
add_l = readl(l2_base + SIFIVE_L2_DIRECCFAIL_LOW);
|
||||
/* Reading this register clears the DirFail interrupt sig */
|
||||
readl(l2_base + SIFIVE_L2_DIRECCFAIL_COUNT);
|
||||
atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE,
|
||||
"DirECCFail");
|
||||
panic("L2CACHE: DirFail @ 0x%08X.%08X\n", add_h, add_l);
|
||||
}
|
||||
if (irq == g_irq[DATA_CORR]) {
|
||||
add_h = readl(l2_base + SIFIVE_L2_DATECCFIX_HIGH);
|
||||
add_l = readl(l2_base + SIFIVE_L2_DATECCFIX_LOW);
|
||||
pr_err("L2CACHE: DataError @ 0x%08X.%08X\n", add_h, add_l);
|
||||
/* Reading this register clears the DataError interrupt sig */
|
||||
readl(l2_base + SIFIVE_L2_DATECCFIX_COUNT);
|
||||
atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE,
|
||||
"DatECCFix");
|
||||
}
|
||||
if (irq == g_irq[DATA_UNCORR]) {
|
||||
add_h = readl(l2_base + SIFIVE_L2_DATECCFAIL_HIGH);
|
||||
add_l = readl(l2_base + SIFIVE_L2_DATECCFAIL_LOW);
|
||||
pr_err("L2CACHE: DataFail @ 0x%08X.%08X\n", add_h, add_l);
|
||||
/* Reading this register clears the DataFail interrupt sig */
|
||||
readl(l2_base + SIFIVE_L2_DATECCFAIL_COUNT);
|
||||
atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE,
|
||||
"DatECCFail");
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __init sifive_l2_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
int i, rc, intr_num;
|
||||
|
||||
np = of_find_matching_node(NULL, sifive_l2_ids);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
if (of_address_to_resource(np, 0, &res))
|
||||
return -ENODEV;
|
||||
|
||||
l2_base = ioremap(res.start, resource_size(&res));
|
||||
if (!l2_base)
|
||||
return -ENOMEM;
|
||||
|
||||
intr_num = of_property_count_u32_elems(np, "interrupts");
|
||||
if (!intr_num) {
|
||||
pr_err("L2CACHE: no interrupts property\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (i = 0; i < intr_num; i++) {
|
||||
g_irq[i] = irq_of_parse_and_map(np, i);
|
||||
rc = request_irq(g_irq[i], l2_int_handler, 0, "l2_ecc", NULL);
|
||||
if (rc) {
|
||||
pr_err("L2CACHE: Could not request IRQ %d\n", g_irq[i]);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
l2_config_read();
|
||||
|
||||
l2_cache_ops.get_priv_group = l2_get_priv_group;
|
||||
riscv_set_cacheinfo_ops(&l2_cache_ops);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
setup_sifive_debug();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
device_initcall(sifive_l2_init);
|
@ -602,21 +602,6 @@ config SERIAL_MUX_CONSOLE
|
||||
select SERIAL_CORE_CONSOLE
|
||||
default y
|
||||
|
||||
config PDC_CONSOLE
|
||||
bool "PDC software console support"
|
||||
depends on PARISC && !SERIAL_MUX && VT
|
||||
help
|
||||
Saying Y here will enable the software based PDC console to be
|
||||
used as the system console. This is useful for machines in
|
||||
which the hardware based console has not been written yet. The
|
||||
following steps must be completed to use the PDC console:
|
||||
|
||||
1. create the device entry (mknod /dev/ttyB0 c 11 0)
|
||||
2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
|
||||
3. Add device ttyB0 to /etc/securetty (if you want to log on as
|
||||
root on this console.)
|
||||
4. Change the kernel command console parameter to: console=ttyB0
|
||||
|
||||
config SERIAL_SUNSAB
|
||||
tristate "Sun Siemens SAB82532 serial support"
|
||||
depends on SPARC && PCI
|
||||
|
@ -1298,7 +1298,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
|
||||
|
||||
/* limit fbsize to max visible screen size */
|
||||
if (fix->smem_len > yres*fix->line_length)
|
||||
fix->smem_len = yres*fix->line_length;
|
||||
fix->smem_len = ALIGN(yres*fix->line_length, 4*1024*1024);
|
||||
|
||||
fix->accel = FB_ACCEL_NONE;
|
||||
|
||||
|
@ -363,13 +363,14 @@ static struct page *ext4_read_merkle_tree_page(struct inode *inode,
|
||||
pgoff_t index,
|
||||
unsigned long num_ra_pages)
|
||||
{
|
||||
DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
|
||||
struct page *page;
|
||||
|
||||
index += ext4_verity_metadata_pos(inode) >> PAGE_SHIFT;
|
||||
|
||||
page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
|
||||
if (!page || !PageUptodate(page)) {
|
||||
DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
|
||||
|
||||
if (page)
|
||||
put_page(page);
|
||||
else if (num_ra_pages > 1)
|
||||
|
@ -258,13 +258,14 @@ static struct page *f2fs_read_merkle_tree_page(struct inode *inode,
|
||||
pgoff_t index,
|
||||
unsigned long num_ra_pages)
|
||||
{
|
||||
DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
|
||||
struct page *page;
|
||||
|
||||
index += f2fs_verity_metadata_pos(inode) >> PAGE_SHIFT;
|
||||
|
||||
page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
|
||||
if (!page || !PageUptodate(page)) {
|
||||
DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
|
||||
|
||||
if (page)
|
||||
put_page(page);
|
||||
else if (num_ra_pages > 1)
|
||||
|
@ -428,6 +428,9 @@ struct cgroup {
|
||||
struct cgroup_file procs_file; /* handle for "cgroup.procs" */
|
||||
struct cgroup_file events_file; /* handle for "cgroup.events" */
|
||||
|
||||
/* handles for "{cpu,memory,io,irq}.pressure" */
|
||||
struct cgroup_file psi_files[NR_PSI_RESOURCES];
|
||||
|
||||
/*
|
||||
* The bitmask of subsystems enabled on the child cgroups.
|
||||
* ->subtree_control is the one configured through
|
||||
|
@ -682,11 +682,6 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp)
|
||||
pr_cont_kernfs_path(cgrp->kn);
|
||||
}
|
||||
|
||||
static inline struct psi_group *cgroup_psi(struct cgroup *cgrp)
|
||||
{
|
||||
return cgrp->psi;
|
||||
}
|
||||
|
||||
bool cgroup_psi_enabled(void);
|
||||
|
||||
static inline void cgroup_init_kthreadd(void)
|
||||
|
@ -8,6 +8,20 @@
|
||||
#ifndef __LINUX_CLK_SPEAR_H
|
||||
#define __LINUX_CLK_SPEAR_H
|
||||
|
||||
#ifdef CONFIG_ARCH_SPEAR3XX
|
||||
void __init spear3xx_clk_init(void __iomem *misc_base,
|
||||
void __iomem *soc_config_base);
|
||||
#else
|
||||
static inline void __init spear3xx_clk_init(void __iomem *misc_base,
|
||||
void __iomem *soc_config_base) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_SPEAR6XX
|
||||
void __init spear6xx_clk_init(void __iomem *misc_base);
|
||||
#else
|
||||
static inline void __init spear6xx_clk_init(void __iomem *misc_base) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_SPEAR1310
|
||||
void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base);
|
||||
#else
|
||||
|
@ -484,6 +484,12 @@ static inline struct damon_region *damon_first_region(struct damon_target *t)
|
||||
return list_first_entry(&t->regions_list, struct damon_region, list);
|
||||
}
|
||||
|
||||
static inline unsigned long damon_sz_region(struct damon_region *r)
|
||||
{
|
||||
return r->ar.end - r->ar.start;
|
||||
}
|
||||
|
||||
|
||||
#define damon_for_each_region(r, t) \
|
||||
list_for_each_entry(r, &t->regions_list, list)
|
||||
|
||||
|
@ -187,6 +187,7 @@ static inline bool folio_is_device_coherent(const struct folio *folio)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ZONE_DEVICE
|
||||
void zone_device_page_init(struct page *page);
|
||||
void *memremap_pages(struct dev_pagemap *pgmap, int nid);
|
||||
void memunmap_pages(struct dev_pagemap *pgmap);
|
||||
void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap);
|
||||
|
@ -62,6 +62,8 @@ extern const char *migrate_reason_names[MR_TYPES];
|
||||
#ifdef CONFIG_MIGRATION
|
||||
|
||||
extern void putback_movable_pages(struct list_head *l);
|
||||
int migrate_folio_extra(struct address_space *mapping, struct folio *dst,
|
||||
struct folio *src, enum migrate_mode mode, int extra_count);
|
||||
int migrate_folio(struct address_space *mapping, struct folio *dst,
|
||||
struct folio *src, enum migrate_mode mode);
|
||||
extern int migrate_pages(struct list_head *l, new_page_t new, free_page_t free,
|
||||
@ -197,11 +199,24 @@ struct migrate_vma {
|
||||
*/
|
||||
void *pgmap_owner;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Set to vmf->page if this is being called to migrate a page as part of
|
||||
* a migrate_to_ram() callback.
|
||||
*/
|
||||
struct page *fault_page;
|
||||
};
|
||||
|
||||
int migrate_vma_setup(struct migrate_vma *args);
|
||||
void migrate_vma_pages(struct migrate_vma *migrate);
|
||||
void migrate_vma_finalize(struct migrate_vma *migrate);
|
||||
int migrate_device_range(unsigned long *src_pfns, unsigned long start,
|
||||
unsigned long npages);
|
||||
void migrate_device_pages(unsigned long *src_pfns, unsigned long *dst_pfns,
|
||||
unsigned long npages);
|
||||
void migrate_device_finalize(unsigned long *src_pfns,
|
||||
unsigned long *dst_pfns, unsigned long npages);
|
||||
|
||||
#endif /* CONFIG_MIGRATION */
|
||||
|
||||
#endif /* _LINUX_MIGRATE_H */
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/cgroup-defs.h>
|
||||
#include <linux/cgroup.h>
|
||||
|
||||
struct seq_file;
|
||||
struct css_set;
|
||||
@ -18,10 +19,6 @@ extern struct psi_group psi_system;
|
||||
|
||||
void psi_init(void);
|
||||
|
||||
void psi_task_change(struct task_struct *task, int clear, int set);
|
||||
void psi_task_switch(struct task_struct *prev, struct task_struct *next,
|
||||
bool sleep);
|
||||
|
||||
void psi_memstall_enter(unsigned long *flags);
|
||||
void psi_memstall_leave(unsigned long *flags);
|
||||
|
||||
@ -34,9 +31,15 @@ __poll_t psi_trigger_poll(void **trigger_ptr, struct file *file,
|
||||
poll_table *wait);
|
||||
|
||||
#ifdef CONFIG_CGROUPS
|
||||
static inline struct psi_group *cgroup_psi(struct cgroup *cgrp)
|
||||
{
|
||||
return cgroup_ino(cgrp) == 1 ? &psi_system : cgrp->psi;
|
||||
}
|
||||
|
||||
int psi_cgroup_alloc(struct cgroup *cgrp);
|
||||
void psi_cgroup_free(struct cgroup *cgrp);
|
||||
void cgroup_move_task(struct task_struct *p, struct css_set *to);
|
||||
void psi_cgroup_restart(struct psi_group *group);
|
||||
#endif
|
||||
|
||||
#else /* CONFIG_PSI */
|
||||
@ -58,6 +61,7 @@ static inline void cgroup_move_task(struct task_struct *p, struct css_set *to)
|
||||
{
|
||||
rcu_assign_pointer(p->cgroups, to);
|
||||
}
|
||||
static inline void psi_cgroup_restart(struct psi_group *group) {}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_PSI */
|
||||
|
@ -15,13 +15,6 @@ enum psi_task_count {
|
||||
NR_IOWAIT,
|
||||
NR_MEMSTALL,
|
||||
NR_RUNNING,
|
||||
/*
|
||||
* This can't have values other than 0 or 1 and could be
|
||||
* implemented as a bit flag. But for now we still have room
|
||||
* in the first cacheline of psi_group_cpu, and this way we
|
||||
* don't have to special case any state tracking for it.
|
||||
*/
|
||||
NR_ONCPU,
|
||||
/*
|
||||
* For IO and CPU stalls the presence of running/oncpu tasks
|
||||
* in the domain means a partial rather than a full stall.
|
||||
@ -32,22 +25,27 @@ enum psi_task_count {
|
||||
* threads and memstall ones.
|
||||
*/
|
||||
NR_MEMSTALL_RUNNING,
|
||||
NR_PSI_TASK_COUNTS = 5,
|
||||
NR_PSI_TASK_COUNTS = 4,
|
||||
};
|
||||
|
||||
/* Task state bitmasks */
|
||||
#define TSK_IOWAIT (1 << NR_IOWAIT)
|
||||
#define TSK_MEMSTALL (1 << NR_MEMSTALL)
|
||||
#define TSK_RUNNING (1 << NR_RUNNING)
|
||||
#define TSK_ONCPU (1 << NR_ONCPU)
|
||||
#define TSK_MEMSTALL_RUNNING (1 << NR_MEMSTALL_RUNNING)
|
||||
|
||||
/* Only one task can be scheduled, no corresponding task count */
|
||||
#define TSK_ONCPU (1 << NR_PSI_TASK_COUNTS)
|
||||
|
||||
/* Resources that workloads could be stalled on */
|
||||
enum psi_res {
|
||||
PSI_IO,
|
||||
PSI_MEM,
|
||||
PSI_CPU,
|
||||
NR_PSI_RESOURCES = 3,
|
||||
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
|
||||
PSI_IRQ,
|
||||
#endif
|
||||
NR_PSI_RESOURCES,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -63,11 +61,17 @@ enum psi_states {
|
||||
PSI_MEM_FULL,
|
||||
PSI_CPU_SOME,
|
||||
PSI_CPU_FULL,
|
||||
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
|
||||
PSI_IRQ_FULL,
|
||||
#endif
|
||||
/* Only per-CPU, to weigh the CPU in the global average: */
|
||||
PSI_NONIDLE,
|
||||
NR_PSI_STATES = 7,
|
||||
NR_PSI_STATES,
|
||||
};
|
||||
|
||||
/* Use one bit in the state mask to track TSK_ONCPU */
|
||||
#define PSI_ONCPU (1 << NR_PSI_STATES)
|
||||
|
||||
enum psi_aggregators {
|
||||
PSI_AVGS = 0,
|
||||
PSI_POLL,
|
||||
@ -147,6 +151,9 @@ struct psi_trigger {
|
||||
};
|
||||
|
||||
struct psi_group {
|
||||
struct psi_group *parent;
|
||||
bool enabled;
|
||||
|
||||
/* Protects data used by the aggregator */
|
||||
struct mutex avgs_lock;
|
||||
|
||||
@ -188,6 +195,8 @@ struct psi_group {
|
||||
|
||||
#else /* CONFIG_PSI */
|
||||
|
||||
#define NR_PSI_RESOURCES 0
|
||||
|
||||
struct psi_group { };
|
||||
|
||||
#endif /* CONFIG_PSI */
|
||||
|
@ -873,8 +873,6 @@ struct task_struct {
|
||||
struct mm_struct *mm;
|
||||
struct mm_struct *active_mm;
|
||||
|
||||
/* Per-thread vma caching: */
|
||||
|
||||
#ifdef SPLIT_RSS_COUNTING
|
||||
struct task_rss_stat rss_stat;
|
||||
#endif
|
||||
|
16
include/soc/sifive/sifive_ccache.h
Normal file
16
include/soc/sifive/sifive_ccache.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* SiFive Composable Cache Controller header file
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SOC_SIFIVE_CCACHE_H
|
||||
#define __SOC_SIFIVE_CCACHE_H
|
||||
|
||||
extern int register_sifive_ccache_error_notifier(struct notifier_block *nb);
|
||||
extern int unregister_sifive_ccache_error_notifier(struct notifier_block *nb);
|
||||
|
||||
#define SIFIVE_CCACHE_ERR_TYPE_CE 0
|
||||
#define SIFIVE_CCACHE_ERR_TYPE_UE 1
|
||||
|
||||
#endif /* __SOC_SIFIVE_CCACHE_H */
|
@ -1,16 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* SiFive L2 Cache Controller header file
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SOC_SIFIVE_L2_CACHE_H
|
||||
#define __SOC_SIFIVE_L2_CACHE_H
|
||||
|
||||
extern int register_sifive_l2_error_notifier(struct notifier_block *nb);
|
||||
extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb);
|
||||
|
||||
#define SIFIVE_L2_ERR_TYPE_CE 0
|
||||
#define SIFIVE_L2_ERR_TYPE_UE 1
|
||||
|
||||
#endif /* __SOC_SIFIVE_L2_CACHE_H */
|
@ -592,11 +592,11 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
|
||||
#define snd_hdac_stream_readb(dev, reg) \
|
||||
snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
#define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
|
||||
readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
|
||||
delay_us, timeout_us)
|
||||
read_poll_timeout_atomic(snd_hdac_reg_readb, val, cond, delay_us, timeout_us, \
|
||||
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
#define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
|
||||
readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
|
||||
delay_us, timeout_us)
|
||||
read_poll_timeout_atomic(snd_hdac_reg_readl, val, cond, delay_us, timeout_us, \
|
||||
false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
|
||||
|
||||
/* update a register, pass without AZX_REG_ prefix */
|
||||
#define snd_hdac_stream_updatel(dev, reg, mask, val) \
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user