aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/cxl/fault.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-29 14:11:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-29 14:11:44 -0400
commit19be9e8aa7820e4a8266d779476e057af7b798be (patch)
treed769328beb56b30bd050c77e307853c3708c0607 /drivers/misc/cxl/fault.c
parent9f76628da20f96a179ca62b504886f99ecc29223 (diff)
parent2c0a33f9861d38631245f7ef434ecad3413324fb (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux
Pull powerpc updates from Michael Ellerman: "There's some bug fixes or cleanups to facilitate fixes, a MAINTAINERS update, and a new syscall (bpf)" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux: powerpc/numa: ensure per-cpu NUMA mappings are correct on topology update powerpc/numa: use cached value of update->cpu in update_cpu_topology cxl: Fix PSL error due to duplicate segment table entries powerpc/mm: Use appropriate ESID mask in copro_calculate_slb() cxl: Refactor cxl_load_segment() and find_free_sste() cxl: Disable secondary hash in segment table Revert "powerpc/powernv: Fix endian bug in LPC bus debugfs accessors" powernv: Use _GLOBAL_TOC for opal wrappers powerpc: Wire up sys_bpf() syscall MAINTAINERS: nx-842 driver maintainer change powerpc/mm: Remove redundant #if case powerpc/mm: Fix build error with hugetlfs disabled
Diffstat (limited to 'drivers/misc/cxl/fault.c')
-rw-r--r--drivers/misc/cxl/fault.c74
1 files changed, 39 insertions, 35 deletions
diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c
index 69506ebd4d07..c99e896604ee 100644
--- a/drivers/misc/cxl/fault.c
+++ b/drivers/misc/cxl/fault.c
@@ -21,60 +21,64 @@
21 21
22#include "cxl.h" 22#include "cxl.h"
23 23
24static struct cxl_sste* find_free_sste(struct cxl_sste *primary_group, 24static bool sste_matches(struct cxl_sste *sste, struct copro_slb *slb)
25 bool sec_hash,
26 struct cxl_sste *secondary_group,
27 unsigned int *lru)
28{ 25{
29 unsigned int i, entry; 26 return ((sste->vsid_data == cpu_to_be64(slb->vsid)) &&
30 struct cxl_sste *sste, *group = primary_group; 27 (sste->esid_data == cpu_to_be64(slb->esid)));
31 28}
32 for (i = 0; i < 2; i++) { 29
33 for (entry = 0; entry < 8; entry++) { 30/*
34 sste = group + entry; 31 * This finds a free SSTE for the given SLB, or returns NULL if it's already in
35 if (!(be64_to_cpu(sste->esid_data) & SLB_ESID_V)) 32 * the segment table.
36 return sste; 33 */
37 } 34static struct cxl_sste* find_free_sste(struct cxl_context *ctx,
38 if (!sec_hash) 35 struct copro_slb *slb)
39 break; 36{
40 group = secondary_group; 37 struct cxl_sste *primary, *sste, *ret = NULL;
38 unsigned int mask = (ctx->sst_size >> 7) - 1; /* SSTP0[SegTableSize] */
39 unsigned int entry;
40 unsigned int hash;
41
42 if (slb->vsid & SLB_VSID_B_1T)
43 hash = (slb->esid >> SID_SHIFT_1T) & mask;
44 else /* 256M */
45 hash = (slb->esid >> SID_SHIFT) & mask;
46
47 primary = ctx->sstp + (hash << 3);
48
49 for (entry = 0, sste = primary; entry < 8; entry++, sste++) {
50 if (!ret && !(be64_to_cpu(sste->esid_data) & SLB_ESID_V))
51 ret = sste;
52 if (sste_matches(sste, slb))
53 return NULL;
41 } 54 }
55 if (ret)
56 return ret;
57
42 /* Nothing free, select an entry to cast out */ 58 /* Nothing free, select an entry to cast out */
43 if (sec_hash && (*lru & 0x8)) 59 ret = primary + ctx->sst_lru;
44 sste = secondary_group + (*lru & 0x7); 60 ctx->sst_lru = (ctx->sst_lru + 1) & 0x7;
45 else
46 sste = primary_group + (*lru & 0x7);
47 *lru = (*lru + 1) & 0xf;
48 61
49 return sste; 62 return ret;
50} 63}
51 64
52static void cxl_load_segment(struct cxl_context *ctx, struct copro_slb *slb) 65static void cxl_load_segment(struct cxl_context *ctx, struct copro_slb *slb)
53{ 66{
54 /* mask is the group index, we search primary and secondary here. */ 67 /* mask is the group index, we search primary and secondary here. */
55 unsigned int mask = (ctx->sst_size >> 7)-1; /* SSTP0[SegTableSize] */
56 bool sec_hash = 1;
57 struct cxl_sste *sste; 68 struct cxl_sste *sste;
58 unsigned int hash;
59 unsigned long flags; 69 unsigned long flags;
60 70
61
62 sec_hash = !!(cxl_p1n_read(ctx->afu, CXL_PSL_SR_An) & CXL_PSL_SR_An_SC);
63
64 if (slb->vsid & SLB_VSID_B_1T)
65 hash = (slb->esid >> SID_SHIFT_1T) & mask;
66 else /* 256M */
67 hash = (slb->esid >> SID_SHIFT) & mask;
68
69 spin_lock_irqsave(&ctx->sste_lock, flags); 71 spin_lock_irqsave(&ctx->sste_lock, flags);
70 sste = find_free_sste(ctx->sstp + (hash << 3), sec_hash, 72 sste = find_free_sste(ctx, slb);
71 ctx->sstp + ((~hash & mask) << 3), &ctx->sst_lru); 73 if (!sste)
74 goto out_unlock;
72 75
73 pr_devel("CXL Populating SST[%li]: %#llx %#llx\n", 76 pr_devel("CXL Populating SST[%li]: %#llx %#llx\n",
74 sste - ctx->sstp, slb->vsid, slb->esid); 77 sste - ctx->sstp, slb->vsid, slb->esid);
75 78
76 sste->vsid_data = cpu_to_be64(slb->vsid); 79 sste->vsid_data = cpu_to_be64(slb->vsid);
77 sste->esid_data = cpu_to_be64(slb->esid); 80 sste->esid_data = cpu_to_be64(slb->esid);
81out_unlock:
78 spin_unlock_irqrestore(&ctx->sste_lock, flags); 82 spin_unlock_irqrestore(&ctx->sste_lock, flags);
79} 83}
80 84