Skip to content

Commit 8e2baac

Browse files
committed
Merge tag 'cache-for-v6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux into soc/drivers-late
standalone cache drivers for v6.19 ccache: Add a compatible for the pic64gx SoC. No driver change needed, as it falls back to the PolarFire SoC. hisi hha/generic cpu cache maintenance: Add support for a non-architectural mechanism for invalidating memory regions, needed for some cxl implementations on arm64 (and probably elsewhere in the future). The HiSilicon Hydra Home Agent is the first driver to provide this support. Signed-off-by: Conor Dooley <conor.dooley@microchip.com> * tag 'cache-for-v6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux: MAINTAINERS: refer to intended file in STANDALONE CACHE CONTROLLER DRIVERS cache: Support cache maintenance for HiSilicon SoC Hydra Home Agent cache: Make top level Kconfig menu a boolean dependent on RISCV MAINTAINERS: Add Jonathan Cameron to drivers/cache and add lib/cache_maint.c + header arm64: Select GENERIC_CPU_CACHE_MAINTENANCE lib: Support ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION memregion: Support fine grained invalidate by cpu_cache_invalidate_memregion() memregion: Drop unused IORES_DESC_* parameter from cpu_cache_invalidate_memregion() dt-bindings: cache: sifive,ccache0: add a pic64gx compatible Signed-off-by: Arnd Bergmann <arnd@arndb.de>
2 parents 909752d + 055bcc5 commit 8e2baac

15 files changed

Lines changed: 462 additions & 12 deletions

File tree

Documentation/devicetree/bindings/cache/sifive,ccache0.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ properties:
4848
- const: microchip,mpfs-ccache
4949
- const: sifive,fu540-c000-ccache
5050
- const: cache
51+
- items:
52+
- const: microchip,pic64gx-ccache
53+
- const: microchip,mpfs-ccache
54+
- const: sifive,fu540-c000-ccache
55+
- const: cache
5156

5257
cache-block-size:
5358
const: 64

MAINTAINERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24451,10 +24451,13 @@ F: drivers/staging/
2445124451

2445224452
STANDALONE CACHE CONTROLLER DRIVERS
2445324453
M: Conor Dooley <conor@kernel.org>
24454+
M: Jonathan Cameron <jonathan.cameron@huawei.com>
2445424455
S: Maintained
2445524456
T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
2445624457
F: Documentation/devicetree/bindings/cache/
2445724458
F: drivers/cache
24459+
F: include/linux/cache_coherency.h
24460+
F: lib/cache_maint.c
2445824461

2445924462
STARFIRE/DURALAN NETWORK DRIVER
2446024463
M: Ion Badulescu <ionut@badula.org>

arch/arm64/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ config ARM64
2121
select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
2222
select ARCH_HAS_CACHE_LINE_SIZE
2323
select ARCH_HAS_CC_PLATFORM
24+
select ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION
2425
select ARCH_HAS_CURRENT_STACK_POINTER
2526
select ARCH_HAS_DEBUG_VIRTUAL
2627
select ARCH_HAS_DEBUG_VM_PGTABLE
@@ -149,6 +150,7 @@ config ARM64
149150
select GENERIC_ARCH_TOPOLOGY
150151
select GENERIC_CLOCKEVENTS_BROADCAST
151152
select GENERIC_CPU_AUTOPROBE
153+
select GENERIC_CPU_CACHE_MAINTENANCE
152154
select GENERIC_CPU_DEVICES
153155
select GENERIC_CPU_VULNERABILITIES
154156
select GENERIC_EARLY_IOREMAP

arch/x86/mm/pat/set_memory.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ bool cpu_cache_has_invalidate_memregion(void)
368368
}
369369
EXPORT_SYMBOL_NS_GPL(cpu_cache_has_invalidate_memregion, "DEVMEM");
370370

371-
int cpu_cache_invalidate_memregion(int res_desc)
371+
int cpu_cache_invalidate_memregion(phys_addr_t start, size_t len)
372372
{
373373
if (WARN_ON_ONCE(!cpu_cache_has_invalidate_memregion()))
374374
return -ENXIO;

drivers/cache/Kconfig

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
# SPDX-License-Identifier: GPL-2.0
2-
menu "Cache Drivers"
2+
3+
menuconfig CACHEMAINT_FOR_DMA
4+
bool "Cache management for noncoherent DMA"
5+
depends on RISCV
6+
default y
7+
help
8+
These drivers implement support for noncoherent DMA master devices
9+
on platforms that lack the standard CPU interfaces for this.
10+
11+
if CACHEMAINT_FOR_DMA
312

413
config AX45MP_L2_CACHE
514
bool "Andes Technology AX45MP L2 Cache controller"
6-
depends on RISCV
715
select RISCV_NONSTANDARD_CACHE_OPS
816
help
917
Support for the L2 cache controller on Andes Technology AX45MP platforms.
@@ -16,12 +24,33 @@ config SIFIVE_CCACHE
1624

1725
config STARFIVE_STARLINK_CACHE
1826
bool "StarFive StarLink Cache controller"
19-
depends on RISCV
2027
depends on ARCH_STARFIVE
2128
depends on 64BIT
2229
select RISCV_DMA_NONCOHERENT
2330
select RISCV_NONSTANDARD_CACHE_OPS
2431
help
2532
Support for the StarLink cache controller IP from StarFive.
2633

27-
endmenu
34+
endif #CACHEMAINT_FOR_DMA
35+
36+
menuconfig CACHEMAINT_FOR_HOTPLUG
37+
bool "Cache management for memory hot plug like operations"
38+
depends on GENERIC_CPU_CACHE_MAINTENANCE
39+
help
40+
These drivers implement cache management for flows where it is necessary
41+
to flush data from all host caches.
42+
43+
if CACHEMAINT_FOR_HOTPLUG
44+
45+
config HISI_SOC_HHA
46+
tristate "HiSilicon Hydra Home Agent (HHA) device driver"
47+
depends on (ARM64 && ACPI) || COMPILE_TEST
48+
help
49+
The Hydra Home Agent (HHA) is responsible for cache coherency
50+
on the SoC. This drivers enables the cache maintenance functions of
51+
the HHA.
52+
53+
This driver can be built as a module. If so, the module will be
54+
called hisi_soc_hha.
55+
56+
endif #CACHEMAINT_FOR_HOTPLUG

drivers/cache/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o
44
obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
55
obj-$(CONFIG_STARFIVE_STARLINK_CACHE) += starfive_starlink_cache.o
6+
7+
obj-$(CONFIG_HISI_SOC_HHA) += hisi_soc_hha.o

drivers/cache/hisi_soc_hha.c

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Driver for HiSilicon Hydra Home Agent (HHA).
4+
*
5+
* Copyright (c) 2025 HiSilicon Technologies Co., Ltd.
6+
* Author: Yicong Yang <yangyicong@hisilicon.com>
7+
* Yushan Wang <wangyushan12@huawei.com>
8+
*
9+
* A system typically contains multiple HHAs. Each is responsible for a subset
10+
* of the physical addresses in the system, but interleave can make the mapping
11+
* from a particular cache line to a responsible HHA complex. As such no
12+
* filtering is done in the driver, with the hardware being responsible for
13+
* responding with success for even if it was not responsible for any addresses
14+
* in the range on which the operation was requested.
15+
*/
16+
17+
#include <linux/bitfield.h>
18+
#include <linux/cache_coherency.h>
19+
#include <linux/dev_printk.h>
20+
#include <linux/init.h>
21+
#include <linux/io.h>
22+
#include <linux/iopoll.h>
23+
#include <linux/kernel.h>
24+
#include <linux/memregion.h>
25+
#include <linux/module.h>
26+
#include <linux/mod_devicetable.h>
27+
#include <linux/mutex.h>
28+
#include <linux/platform_device.h>
29+
30+
#define HISI_HHA_CTRL 0x5004
31+
#define HISI_HHA_CTRL_EN BIT(0)
32+
#define HISI_HHA_CTRL_RANGE BIT(1)
33+
#define HISI_HHA_CTRL_TYPE GENMASK(3, 2)
34+
#define HISI_HHA_START_L 0x5008
35+
#define HISI_HHA_START_H 0x500c
36+
#define HISI_HHA_LEN_L 0x5010
37+
#define HISI_HHA_LEN_H 0x5014
38+
39+
/* The maintain operation performs in a 128 Byte granularity */
40+
#define HISI_HHA_MAINT_ALIGN 128
41+
42+
#define HISI_HHA_POLL_GAP_US 10
43+
#define HISI_HHA_POLL_TIMEOUT_US 50000
44+
45+
struct hisi_soc_hha {
46+
/* Must be first element */
47+
struct cache_coherency_ops_inst cci;
48+
/* Locks HHA instance to forbid overlapping access. */
49+
struct mutex lock;
50+
void __iomem *base;
51+
};
52+
53+
static bool hisi_hha_cache_maintain_wait_finished(struct hisi_soc_hha *soc_hha)
54+
{
55+
u32 val;
56+
57+
return !readl_poll_timeout_atomic(soc_hha->base + HISI_HHA_CTRL, val,
58+
!(val & HISI_HHA_CTRL_EN),
59+
HISI_HHA_POLL_GAP_US,
60+
HISI_HHA_POLL_TIMEOUT_US);
61+
}
62+
63+
static int hisi_soc_hha_wbinv(struct cache_coherency_ops_inst *cci,
64+
struct cc_inval_params *invp)
65+
{
66+
struct hisi_soc_hha *soc_hha =
67+
container_of(cci, struct hisi_soc_hha, cci);
68+
phys_addr_t top, addr = invp->addr;
69+
size_t size = invp->size;
70+
u32 reg;
71+
72+
if (!size)
73+
return -EINVAL;
74+
75+
addr = ALIGN_DOWN(addr, HISI_HHA_MAINT_ALIGN);
76+
top = ALIGN(addr + size, HISI_HHA_MAINT_ALIGN);
77+
size = top - addr;
78+
79+
guard(mutex)(&soc_hha->lock);
80+
81+
if (!hisi_hha_cache_maintain_wait_finished(soc_hha))
82+
return -EBUSY;
83+
84+
/*
85+
* Hardware will search for addresses ranging [addr, addr + size - 1],
86+
* last byte included, and perform maintenance in 128 byte granules
87+
* on those cachelines which contain the addresses. If a given instance
88+
* is either not responsible for a cacheline or that cacheline is not
89+
* currently present then the search will fail, no operation will be
90+
* necessary and the device will report success.
91+
*/
92+
size -= 1;
93+
94+
writel(lower_32_bits(addr), soc_hha->base + HISI_HHA_START_L);
95+
writel(upper_32_bits(addr), soc_hha->base + HISI_HHA_START_H);
96+
writel(lower_32_bits(size), soc_hha->base + HISI_HHA_LEN_L);
97+
writel(upper_32_bits(size), soc_hha->base + HISI_HHA_LEN_H);
98+
99+
reg = FIELD_PREP(HISI_HHA_CTRL_TYPE, 1); /* Clean Invalid */
100+
reg |= HISI_HHA_CTRL_RANGE | HISI_HHA_CTRL_EN;
101+
writel(reg, soc_hha->base + HISI_HHA_CTRL);
102+
103+
return 0;
104+
}
105+
106+
static int hisi_soc_hha_done(struct cache_coherency_ops_inst *cci)
107+
{
108+
struct hisi_soc_hha *soc_hha =
109+
container_of(cci, struct hisi_soc_hha, cci);
110+
111+
guard(mutex)(&soc_hha->lock);
112+
if (!hisi_hha_cache_maintain_wait_finished(soc_hha))
113+
return -ETIMEDOUT;
114+
115+
return 0;
116+
}
117+
118+
static const struct cache_coherency_ops hha_ops = {
119+
.wbinv = hisi_soc_hha_wbinv,
120+
.done = hisi_soc_hha_done,
121+
};
122+
123+
static int hisi_soc_hha_probe(struct platform_device *pdev)
124+
{
125+
struct hisi_soc_hha *soc_hha;
126+
struct resource *mem;
127+
int ret;
128+
129+
soc_hha = cache_coherency_ops_instance_alloc(&hha_ops,
130+
struct hisi_soc_hha, cci);
131+
if (!soc_hha)
132+
return -ENOMEM;
133+
134+
platform_set_drvdata(pdev, soc_hha);
135+
136+
mutex_init(&soc_hha->lock);
137+
138+
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
139+
if (!mem) {
140+
ret = -ENOMEM;
141+
goto err_free_cci;
142+
}
143+
144+
soc_hha->base = ioremap(mem->start, resource_size(mem));
145+
if (!soc_hha->base) {
146+
ret = dev_err_probe(&pdev->dev, -ENOMEM,
147+
"failed to remap io memory");
148+
goto err_free_cci;
149+
}
150+
151+
ret = cache_coherency_ops_instance_register(&soc_hha->cci);
152+
if (ret)
153+
goto err_iounmap;
154+
155+
return 0;
156+
157+
err_iounmap:
158+
iounmap(soc_hha->base);
159+
err_free_cci:
160+
cache_coherency_ops_instance_put(&soc_hha->cci);
161+
return ret;
162+
}
163+
164+
static void hisi_soc_hha_remove(struct platform_device *pdev)
165+
{
166+
struct hisi_soc_hha *soc_hha = platform_get_drvdata(pdev);
167+
168+
cache_coherency_ops_instance_unregister(&soc_hha->cci);
169+
iounmap(soc_hha->base);
170+
cache_coherency_ops_instance_put(&soc_hha->cci);
171+
}
172+
173+
static const struct acpi_device_id hisi_soc_hha_ids[] = {
174+
{ "HISI0511", },
175+
{ }
176+
};
177+
MODULE_DEVICE_TABLE(acpi, hisi_soc_hha_ids);
178+
179+
static struct platform_driver hisi_soc_hha_driver = {
180+
.driver = {
181+
.name = "hisi_soc_hha",
182+
.acpi_match_table = hisi_soc_hha_ids,
183+
},
184+
.probe = hisi_soc_hha_probe,
185+
.remove = hisi_soc_hha_remove,
186+
};
187+
188+
module_platform_driver(hisi_soc_hha_driver);
189+
190+
MODULE_IMPORT_NS("CACHE_COHERENCY");
191+
MODULE_DESCRIPTION("HiSilicon Hydra Home Agent driver supporting cache maintenance");
192+
MODULE_AUTHOR("Yicong Yang <yangyicong@hisilicon.com>");
193+
MODULE_AUTHOR("Yushan Wang <wangyushan12@huawei.com>");
194+
MODULE_LICENSE("GPL");

drivers/cxl/core/region.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,10 @@ static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
236236
return -ENXIO;
237237
}
238238

239-
cpu_cache_invalidate_memregion(IORES_DESC_CXL);
239+
if (!cxlr->params.res)
240+
return -ENXIO;
241+
cpu_cache_invalidate_memregion(cxlr->params.res->start,
242+
resource_size(cxlr->params.res));
240243
return 0;
241244
}
242245

drivers/nvdimm/region.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ static void nd_region_remove(struct device *dev)
110110
* here is ok.
111111
*/
112112
if (cpu_cache_has_invalidate_memregion())
113-
cpu_cache_invalidate_memregion(IORES_DESC_PERSISTENT_MEMORY);
113+
cpu_cache_invalidate_all();
114114
}
115115

116116
static int child_notify(struct device *dev, void *data)

drivers/nvdimm/region_devs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static int nd_region_invalidate_memregion(struct nd_region *nd_region)
9090
}
9191
}
9292

93-
cpu_cache_invalidate_memregion(IORES_DESC_PERSISTENT_MEMORY);
93+
cpu_cache_invalidate_all();
9494
out:
9595
for (i = 0; i < nd_region->ndr_mappings; i++) {
9696
struct nd_mapping *nd_mapping = &nd_region->mapping[i];

0 commit comments

Comments
 (0)