diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/misc/cxl/fault.c | 74 | ||||
| -rw-r--r-- | drivers/misc/cxl/native.c | 4 |
2 files changed, 41 insertions, 37 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 | ||
| 24 | static struct cxl_sste* find_free_sste(struct cxl_sste *primary_group, | 24 | static 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 | } | 34 | static 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 | ||
| 52 | static void cxl_load_segment(struct cxl_context *ctx, struct copro_slb *slb) | 65 | static 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); |
| 81 | out_unlock: | ||
| 78 | spin_unlock_irqrestore(&ctx->sste_lock, flags); | 82 | spin_unlock_irqrestore(&ctx->sste_lock, flags); |
| 79 | } | 83 | } |
| 80 | 84 | ||
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c index 623286a77114..d47532e8f4f1 100644 --- a/drivers/misc/cxl/native.c +++ b/drivers/misc/cxl/native.c | |||
| @@ -417,7 +417,7 @@ static int attach_afu_directed(struct cxl_context *ctx, u64 wed, u64 amr) | |||
| 417 | ctx->elem->haurp = 0; /* disable */ | 417 | ctx->elem->haurp = 0; /* disable */ |
| 418 | ctx->elem->sdr = cpu_to_be64(mfspr(SPRN_SDR1)); | 418 | ctx->elem->sdr = cpu_to_be64(mfspr(SPRN_SDR1)); |
| 419 | 419 | ||
| 420 | sr = CXL_PSL_SR_An_SC; | 420 | sr = 0; |
| 421 | if (ctx->master) | 421 | if (ctx->master) |
| 422 | sr |= CXL_PSL_SR_An_MP; | 422 | sr |= CXL_PSL_SR_An_MP; |
| 423 | if (mfspr(SPRN_LPCR) & LPCR_TC) | 423 | if (mfspr(SPRN_LPCR) & LPCR_TC) |
| @@ -508,7 +508,7 @@ static int attach_dedicated(struct cxl_context *ctx, u64 wed, u64 amr) | |||
| 508 | u64 sr; | 508 | u64 sr; |
| 509 | int rc; | 509 | int rc; |
| 510 | 510 | ||
| 511 | sr = CXL_PSL_SR_An_SC; | 511 | sr = 0; |
| 512 | set_endian(sr); | 512 | set_endian(sr); |
| 513 | if (ctx->master) | 513 | if (ctx->master) |
| 514 | sr |= CXL_PSL_SR_An_MP; | 514 | sr |= CXL_PSL_SR_An_MP; |
