build/patch/kernel/media-edge/00110-v91-irq-gic-v3-its.patch

193 lines
5.1 KiB
Diff
Raw Normal View History

--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -45,6 +45,7 @@
#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0)
#define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1)
+#define RDIST_FLAGS_FORCE_NO_LOCAL_CACHE (1 << 2)
#define RD_LOCAL_LPI_ENABLED BIT(0)
#define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1)
@@ -2176,6 +2177,11 @@
{
struct page *prop_page;
+ if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE) {
+ pr_err("ITS ALLOCATE PROP WORKAROUND\n");
+ gfp_flags |= GFP_DMA;
+ }
+
prop_page = alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ));
if (!prop_page)
return NULL;
@@ -2299,6 +2305,7 @@
u32 alloc_pages, psz;
struct page *page;
void *base;
+ gfp_t gfp_flags;
psz = baser->psz;
alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
@@ -2310,7 +2317,10 @@
order = get_order(GITS_BASER_PAGES_MAX * psz);
}
- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order);
+ gfp_flags = GFP_KERNEL | __GFP_ZERO;
+ if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
+ gfp_flags |= GFP_DMA;
+ page = alloc_pages_node(its->numa_node, gfp_flags, order);
if (!page)
return -ENOMEM;
@@ -2356,6 +2366,13 @@
its_write_baser(its, baser, val);
tmp = baser->val;
+
+ if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE) {
+ if (tmp & GITS_BASER_SHAREABILITY_MASK)
+ tmp &= ~GITS_BASER_SHAREABILITY_MASK;
+ else
+ gic_flush_dcache_to_poc(base, PAGE_ORDER_TO_SIZE(order));
+ }
if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
/*
@@ -2939,6 +2956,10 @@
{
struct page *pend_page;
+ if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE) {
+ gfp_flags |= GFP_DMA;
+ }
+
pend_page = alloc_pages(gfp_flags | __GFP_ZERO,
get_order(LPI_PENDBASE_SZ));
if (!pend_page)
@@ -3083,6 +3104,9 @@
gicr_write_propbaser(val, rbase + GICR_PROPBASER);
tmp = gicr_read_propbaser(rbase + GICR_PROPBASER);
+
+ if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
+ tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK;
if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
@@ -3108,6 +3132,9 @@
gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER);
+ if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
+ tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK;
+
if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
/*
* The HW reports non-shareable, we must remove the
@@ -3271,7 +3298,12 @@
/* Allocate memory for 2nd level table */
if (!table[idx]) {
- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
+ gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO;
+ if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE) {
+ gfp_flags |= GFP_DMA;
+ }
+
+ page = alloc_pages_node(its->numa_node, gfp_flags,
get_order(baser->psz));
if (!page)
return false;
@@ -3360,6 +3392,7 @@
int nr_lpis;
int nr_ites;
int sz;
+ gfp_t gfp_flags;
if (!its_alloc_device_table(its, dev_id))
return NULL;
@@ -3367,7 +3400,11 @@
if (WARN_ON(!is_power_of_2(nvecs)))
nvecs = roundup_pow_of_two(nvecs);
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ gfp_flags = GFP_KERNEL;
+ if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
+ gfp_flags |= GFP_DMA;
+
+ dev = kzalloc(sizeof(*dev), gfp_flags);
/*
* Even if the device wants a single LPI, the ITT must be
* sized as a power of two (and you need at least one bit...).
@@ -3375,7 +3412,8 @@
nr_ites = max(2, nvecs);
sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
- itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node);
+
+ itt = kzalloc_node(sz, gfp_flags, its->numa_node);
if (alloc_lpis) {
lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis);
if (lpi_map)
@@ -4695,6 +4733,13 @@
* page. Trick it into doing the right thing...
*/
its->vlpi_redist_offset = SZ_128K;
+ return true;
+}
+
+static bool __maybe_unused its_enable_quirk_rk3568(void *data)
+{
+ gic_rdists->flags |= RDIST_FLAGS_FORCE_NO_LOCAL_CACHE;
+
return true;
}
@@ -4745,6 +4790,13 @@
},
#endif
{
+ .desc = "ITS: Rockchip RK3568 force no_local_cache",
+ .iidr = 0x0201743b,
+ .mask = 0xffffffff,
+ .init = its_enable_quirk_rk3568,
+ },
+
+ {
}
};
@@ -4999,6 +5051,7 @@
struct page *page;
u32 ctlr;
int err;
+ gfp_t gfp_flags;
its_base = its_map_one(res, &err);
if (!its_base)
@@ -5052,7 +5105,11 @@
its->numa_node = numa_node;
- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
+ gfp_flags = GFP_KERNEL | __GFP_ZERO | GFP_DMA;
+// if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
+// gfp_flags |= GFP_DMA;
+
+ page = alloc_pages_node(its->numa_node, gfp_flags,
get_order(ITS_CMD_QUEUE_SZ));
if (!page) {
err = -ENOMEM;
@@ -5082,6 +5139,9 @@
gits_write_cbaser(baser, its->base + GITS_CBASER);
tmp = gits_read_cbaser(its->base + GITS_CBASER);
+
+ if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
+ tmp &= ~GITS_CBASER_SHAREABILITY_MASK;
if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {
if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {