aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/cxl/fault.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c
index cb4f3231b451..c99e896604ee 100644
--- a/drivers/misc/cxl/fault.c
+++ b/drivers/misc/cxl/fault.c
@@ -21,11 +21,20 @@
21 21
22#include "cxl.h" 22#include "cxl.h"
23 23
24/* This finds a free SSTE for the given SLB */ 24static bool sste_matches(struct cxl_sste *sste, struct copro_slb *slb)
25{
26 return ((sste->vsid_data == cpu_to_be64(slb->vsid)) &&
27 (sste->esid_data == cpu_to_be64(slb->esid)));
28}
29
30/*
31 * This finds a free SSTE for the given SLB, or returns NULL if it's already in
32 * the segment table.
33 */
25static struct cxl_sste* find_free_sste(struct cxl_context *ctx, 34static struct cxl_sste* find_free_sste(struct cxl_context *ctx,
26 struct copro_slb *slb) 35 struct copro_slb *slb)
27{ 36{
28 struct cxl_sste *primary, *sste; 37 struct cxl_sste *primary, *sste, *ret = NULL;
29 unsigned int mask = (ctx->sst_size >> 7) - 1; /* SSTP0[SegTableSize] */ 38 unsigned int mask = (ctx->sst_size >> 7) - 1; /* SSTP0[SegTableSize] */
30 unsigned int entry; 39 unsigned int entry;
31 unsigned int hash; 40 unsigned int hash;
@@ -38,15 +47,19 @@ static struct cxl_sste* find_free_sste(struct cxl_context *ctx,
38 primary = ctx->sstp + (hash << 3); 47 primary = ctx->sstp + (hash << 3);
39 48
40 for (entry = 0, sste = primary; entry < 8; entry++, sste++) { 49 for (entry = 0, sste = primary; entry < 8; entry++, sste++) {
41 if (!(be64_to_cpu(sste->esid_data) & SLB_ESID_V)) 50 if (!ret && !(be64_to_cpu(sste->esid_data) & SLB_ESID_V))
42 return sste; 51 ret = sste;
52 if (sste_matches(sste, slb))
53 return NULL;
43 } 54 }
55 if (ret)
56 return ret;
44 57
45 /* Nothing free, select an entry to cast out */ 58 /* Nothing free, select an entry to cast out */
46 sste = primary + ctx->sst_lru; 59 ret = primary + ctx->sst_lru;
47 ctx->sst_lru = (ctx->sst_lru + 1) & 0x7; 60 ctx->sst_lru = (ctx->sst_lru + 1) & 0x7;
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)
@@ -57,12 +70,15 @@ static void cxl_load_segment(struct cxl_context *ctx, struct copro_slb *slb)
57 70
58 spin_lock_irqsave(&ctx->sste_lock, flags); 71 spin_lock_irqsave(&ctx->sste_lock, flags);
59 sste = find_free_sste(ctx, slb); 72 sste = find_free_sste(ctx, slb);
73 if (!sste)
74 goto out_unlock;
60 75
61 pr_devel("CXL Populating SST[%li]: %#llx %#llx\n", 76 pr_devel("CXL Populating SST[%li]: %#llx %#llx\n",
62 sste - ctx->sstp, slb->vsid, slb->esid); 77 sste - ctx->sstp, slb->vsid, slb->esid);
63 78
64 sste->vsid_data = cpu_to_be64(slb->vsid); 79 sste->vsid_data = cpu_to_be64(slb->vsid);
65 sste->esid_data = cpu_to_be64(slb->esid); 80 sste->esid_data = cpu_to_be64(slb->esid);
81out_unlock:
66 spin_unlock_irqrestore(&ctx->sste_lock, flags); 82 spin_unlock_irqrestore(&ctx->sste_lock, flags);
67} 83}
68 84