1f204e0b8SIan Munsie /* 2f204e0b8SIan Munsie * Copyright 2014 IBM Corp. 3f204e0b8SIan Munsie * 4f204e0b8SIan Munsie * This program is free software; you can redistribute it and/or 5f204e0b8SIan Munsie * modify it under the terms of the GNU General Public License 6f204e0b8SIan Munsie * as published by the Free Software Foundation; either version 7f204e0b8SIan Munsie * 2 of the License, or (at your option) any later version. 8f204e0b8SIan Munsie */ 9f204e0b8SIan Munsie 10f204e0b8SIan Munsie #include <linux/spinlock.h> 11f204e0b8SIan Munsie #include <linux/sched.h> 12f204e0b8SIan Munsie #include <linux/slab.h> 13f204e0b8SIan Munsie #include <linux/sched.h> 14f204e0b8SIan Munsie #include <linux/mutex.h> 15f204e0b8SIan Munsie #include <linux/mm.h> 16f204e0b8SIan Munsie #include <linux/uaccess.h> 17f204e0b8SIan Munsie #include <asm/synch.h> 18f204e0b8SIan Munsie #include <misc/cxl.h> 19f204e0b8SIan Munsie 20f204e0b8SIan Munsie #include "cxl.h" 219bcf28cdSIan Munsie #include "trace.h" 22f204e0b8SIan Munsie 23f204e0b8SIan Munsie static int afu_control(struct cxl_afu *afu, u64 command, 24f204e0b8SIan Munsie u64 result, u64 mask, bool enabled) 25f204e0b8SIan Munsie { 26f204e0b8SIan Munsie u64 AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); 27f204e0b8SIan Munsie unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); 289bcf28cdSIan Munsie int rc = 0; 29f204e0b8SIan Munsie 30f204e0b8SIan Munsie spin_lock(&afu->afu_cntl_lock); 31f204e0b8SIan Munsie pr_devel("AFU command starting: %llx\n", command); 32f204e0b8SIan Munsie 339bcf28cdSIan Munsie trace_cxl_afu_ctrl(afu, command); 349bcf28cdSIan Munsie 35f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_AFU_Cntl_An, AFU_Cntl | command); 36f204e0b8SIan Munsie 37f204e0b8SIan Munsie AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); 38f204e0b8SIan Munsie while ((AFU_Cntl & mask) != result) { 39f204e0b8SIan Munsie if (time_after_eq(jiffies, timeout)) { 40f204e0b8SIan Munsie dev_warn(&afu->dev, "WARNING: AFU control timed out!\n"); 419bcf28cdSIan Munsie rc = -EBUSY; 429bcf28cdSIan Munsie goto out; 43f204e0b8SIan Munsie } 44f204e0b8SIan Munsie pr_devel_ratelimited("AFU control... (0x%.16llx)\n", 45f204e0b8SIan Munsie AFU_Cntl | command); 46f204e0b8SIan Munsie cpu_relax(); 47f204e0b8SIan Munsie AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); 48f204e0b8SIan Munsie }; 49f204e0b8SIan Munsie pr_devel("AFU command complete: %llx\n", command); 50f204e0b8SIan Munsie afu->enabled = enabled; 519bcf28cdSIan Munsie out: 529bcf28cdSIan Munsie trace_cxl_afu_ctrl_done(afu, command, rc); 53f204e0b8SIan Munsie spin_unlock(&afu->afu_cntl_lock); 54f204e0b8SIan Munsie 559bcf28cdSIan Munsie return rc; 56f204e0b8SIan Munsie } 57f204e0b8SIan Munsie 58f204e0b8SIan Munsie static int afu_enable(struct cxl_afu *afu) 59f204e0b8SIan Munsie { 60f204e0b8SIan Munsie pr_devel("AFU enable request\n"); 61f204e0b8SIan Munsie 62f204e0b8SIan Munsie return afu_control(afu, CXL_AFU_Cntl_An_E, 63f204e0b8SIan Munsie CXL_AFU_Cntl_An_ES_Enabled, 64f204e0b8SIan Munsie CXL_AFU_Cntl_An_ES_MASK, true); 65f204e0b8SIan Munsie } 66f204e0b8SIan Munsie 67f204e0b8SIan Munsie int cxl_afu_disable(struct cxl_afu *afu) 68f204e0b8SIan Munsie { 69f204e0b8SIan Munsie pr_devel("AFU disable request\n"); 70f204e0b8SIan Munsie 71f204e0b8SIan Munsie return afu_control(afu, 0, CXL_AFU_Cntl_An_ES_Disabled, 72f204e0b8SIan Munsie CXL_AFU_Cntl_An_ES_MASK, false); 73f204e0b8SIan Munsie } 74f204e0b8SIan Munsie 75f204e0b8SIan Munsie /* This will disable as well as reset */ 76b12994fbSMichael Neuling int __cxl_afu_reset(struct cxl_afu *afu) 77f204e0b8SIan Munsie { 78f204e0b8SIan Munsie pr_devel("AFU reset request\n"); 79f204e0b8SIan Munsie 80f204e0b8SIan Munsie return afu_control(afu, CXL_AFU_Cntl_An_RA, 81f204e0b8SIan Munsie CXL_AFU_Cntl_An_RS_Complete | CXL_AFU_Cntl_An_ES_Disabled, 82f204e0b8SIan Munsie CXL_AFU_Cntl_An_RS_MASK | CXL_AFU_Cntl_An_ES_MASK, 83f204e0b8SIan Munsie false); 84f204e0b8SIan Munsie } 85f204e0b8SIan Munsie 861a1a94b8SMichael Neuling int cxl_afu_check_and_enable(struct cxl_afu *afu) 87f204e0b8SIan Munsie { 88f204e0b8SIan Munsie if (afu->enabled) 89f204e0b8SIan Munsie return 0; 90f204e0b8SIan Munsie return afu_enable(afu); 91f204e0b8SIan Munsie } 92f204e0b8SIan Munsie 93f204e0b8SIan Munsie int cxl_psl_purge(struct cxl_afu *afu) 94f204e0b8SIan Munsie { 95f204e0b8SIan Munsie u64 PSL_CNTL = cxl_p1n_read(afu, CXL_PSL_SCNTL_An); 96f204e0b8SIan Munsie u64 AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); 97f204e0b8SIan Munsie u64 dsisr, dar; 98f204e0b8SIan Munsie u64 start, end; 99f204e0b8SIan Munsie unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); 1009bcf28cdSIan Munsie int rc = 0; 1019bcf28cdSIan Munsie 1029bcf28cdSIan Munsie trace_cxl_psl_ctrl(afu, CXL_PSL_SCNTL_An_Pc); 103f204e0b8SIan Munsie 104f204e0b8SIan Munsie pr_devel("PSL purge request\n"); 105f204e0b8SIan Munsie 106f204e0b8SIan Munsie if ((AFU_Cntl & CXL_AFU_Cntl_An_ES_MASK) != CXL_AFU_Cntl_An_ES_Disabled) { 107f204e0b8SIan Munsie WARN(1, "psl_purge request while AFU not disabled!\n"); 108f204e0b8SIan Munsie cxl_afu_disable(afu); 109f204e0b8SIan Munsie } 110f204e0b8SIan Munsie 111f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_SCNTL_An, 112f204e0b8SIan Munsie PSL_CNTL | CXL_PSL_SCNTL_An_Pc); 113f204e0b8SIan Munsie start = local_clock(); 114f204e0b8SIan Munsie PSL_CNTL = cxl_p1n_read(afu, CXL_PSL_SCNTL_An); 115f204e0b8SIan Munsie while ((PSL_CNTL & CXL_PSL_SCNTL_An_Ps_MASK) 116f204e0b8SIan Munsie == CXL_PSL_SCNTL_An_Ps_Pending) { 117f204e0b8SIan Munsie if (time_after_eq(jiffies, timeout)) { 118f204e0b8SIan Munsie dev_warn(&afu->dev, "WARNING: PSL Purge timed out!\n"); 1199bcf28cdSIan Munsie rc = -EBUSY; 1209bcf28cdSIan Munsie goto out; 121f204e0b8SIan Munsie } 122f204e0b8SIan Munsie dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); 123f204e0b8SIan Munsie pr_devel_ratelimited("PSL purging... PSL_CNTL: 0x%.16llx PSL_DSISR: 0x%.16llx\n", PSL_CNTL, dsisr); 124f204e0b8SIan Munsie if (dsisr & CXL_PSL_DSISR_TRANS) { 125f204e0b8SIan Munsie dar = cxl_p2n_read(afu, CXL_PSL_DAR_An); 126f204e0b8SIan Munsie dev_notice(&afu->dev, "PSL purge terminating pending translation, DSISR: 0x%.16llx, DAR: 0x%.16llx\n", dsisr, dar); 127f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE); 128f204e0b8SIan Munsie } else if (dsisr) { 129f204e0b8SIan Munsie dev_notice(&afu->dev, "PSL purge acknowledging pending non-translation fault, DSISR: 0x%.16llx\n", dsisr); 130f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A); 131f204e0b8SIan Munsie } else { 132f204e0b8SIan Munsie cpu_relax(); 133f204e0b8SIan Munsie } 134f204e0b8SIan Munsie PSL_CNTL = cxl_p1n_read(afu, CXL_PSL_SCNTL_An); 135f204e0b8SIan Munsie }; 136f204e0b8SIan Munsie end = local_clock(); 137f204e0b8SIan Munsie pr_devel("PSL purged in %lld ns\n", end - start); 138f204e0b8SIan Munsie 139f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_SCNTL_An, 140f204e0b8SIan Munsie PSL_CNTL & ~CXL_PSL_SCNTL_An_Pc); 1419bcf28cdSIan Munsie out: 1429bcf28cdSIan Munsie trace_cxl_psl_ctrl_done(afu, CXL_PSL_SCNTL_An_Pc, rc); 1439bcf28cdSIan Munsie return rc; 144f204e0b8SIan Munsie } 145f204e0b8SIan Munsie 146f204e0b8SIan Munsie static int spa_max_procs(int spa_size) 147f204e0b8SIan Munsie { 148f204e0b8SIan Munsie /* 149f204e0b8SIan Munsie * From the CAIA: 150f204e0b8SIan Munsie * end_of_SPA_area = SPA_Base + ((n+4) * 128) + (( ((n*8) + 127) >> 7) * 128) + 255 151f204e0b8SIan Munsie * Most of that junk is really just an overly-complicated way of saying 152f204e0b8SIan Munsie * the last 256 bytes are __aligned(128), so it's really: 153f204e0b8SIan Munsie * end_of_SPA_area = end_of_PSL_queue_area + __aligned(128) 255 154f204e0b8SIan Munsie * and 155f204e0b8SIan Munsie * end_of_PSL_queue_area = SPA_Base + ((n+4) * 128) + (n*8) - 1 156f204e0b8SIan Munsie * so 157f204e0b8SIan Munsie * sizeof(SPA) = ((n+4) * 128) + (n*8) + __aligned(128) 256 158f204e0b8SIan Munsie * Ignore the alignment (which is safe in this case as long as we are 159f204e0b8SIan Munsie * careful with our rounding) and solve for n: 160f204e0b8SIan Munsie */ 161f204e0b8SIan Munsie return ((spa_size / 8) - 96) / 17; 162f204e0b8SIan Munsie } 163f204e0b8SIan Munsie 164f204e0b8SIan Munsie static int alloc_spa(struct cxl_afu *afu) 165f204e0b8SIan Munsie { 166f204e0b8SIan Munsie u64 spap; 167f204e0b8SIan Munsie 168f204e0b8SIan Munsie /* Work out how many pages to allocate */ 169f204e0b8SIan Munsie afu->spa_order = 0; 170f204e0b8SIan Munsie do { 171f204e0b8SIan Munsie afu->spa_order++; 172f204e0b8SIan Munsie afu->spa_size = (1 << afu->spa_order) * PAGE_SIZE; 173f204e0b8SIan Munsie afu->spa_max_procs = spa_max_procs(afu->spa_size); 174f204e0b8SIan Munsie } while (afu->spa_max_procs < afu->num_procs); 175f204e0b8SIan Munsie 176f204e0b8SIan Munsie WARN_ON(afu->spa_size > 0x100000); /* Max size supported by the hardware */ 177f204e0b8SIan Munsie 178f204e0b8SIan Munsie if (!(afu->spa = (struct cxl_process_element *) 179f204e0b8SIan Munsie __get_free_pages(GFP_KERNEL | __GFP_ZERO, afu->spa_order))) { 180f204e0b8SIan Munsie pr_err("cxl_alloc_spa: Unable to allocate scheduled process area\n"); 181f204e0b8SIan Munsie return -ENOMEM; 182f204e0b8SIan Munsie } 183f204e0b8SIan Munsie pr_devel("spa pages: %i afu->spa_max_procs: %i afu->num_procs: %i\n", 184f204e0b8SIan Munsie 1<<afu->spa_order, afu->spa_max_procs, afu->num_procs); 185f204e0b8SIan Munsie 186f204e0b8SIan Munsie afu->sw_command_status = (__be64 *)((char *)afu->spa + 187f204e0b8SIan Munsie ((afu->spa_max_procs + 3) * 128)); 188f204e0b8SIan Munsie 189f204e0b8SIan Munsie spap = virt_to_phys(afu->spa) & CXL_PSL_SPAP_Addr; 190f204e0b8SIan Munsie spap |= ((afu->spa_size >> (12 - CXL_PSL_SPAP_Size_Shift)) - 1) & CXL_PSL_SPAP_Size; 191f204e0b8SIan Munsie spap |= CXL_PSL_SPAP_V; 192f204e0b8SIan Munsie pr_devel("cxl: SPA allocated at 0x%p. Max processes: %i, sw_command_status: 0x%p CXL_PSL_SPAP_An=0x%016llx\n", afu->spa, afu->spa_max_procs, afu->sw_command_status, spap); 193f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_SPAP_An, spap); 194f204e0b8SIan Munsie 195f204e0b8SIan Munsie return 0; 196f204e0b8SIan Munsie } 197f204e0b8SIan Munsie 198f204e0b8SIan Munsie static void release_spa(struct cxl_afu *afu) 199f204e0b8SIan Munsie { 200db7933f3SIan Munsie cxl_p1n_write(afu, CXL_PSL_SPAP_An, 0); 201f204e0b8SIan Munsie free_pages((unsigned long) afu->spa, afu->spa_order); 202f204e0b8SIan Munsie } 203f204e0b8SIan Munsie 204f204e0b8SIan Munsie int cxl_tlb_slb_invalidate(struct cxl *adapter) 205f204e0b8SIan Munsie { 206f204e0b8SIan Munsie unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); 207f204e0b8SIan Munsie 208f204e0b8SIan Munsie pr_devel("CXL adapter wide TLBIA & SLBIA\n"); 209f204e0b8SIan Munsie 210f204e0b8SIan Munsie cxl_p1_write(adapter, CXL_PSL_AFUSEL, CXL_PSL_AFUSEL_A); 211f204e0b8SIan Munsie 212f204e0b8SIan Munsie cxl_p1_write(adapter, CXL_PSL_TLBIA, CXL_TLB_SLB_IQ_ALL); 213f204e0b8SIan Munsie while (cxl_p1_read(adapter, CXL_PSL_TLBIA) & CXL_TLB_SLB_P) { 214f204e0b8SIan Munsie if (time_after_eq(jiffies, timeout)) { 215f204e0b8SIan Munsie dev_warn(&adapter->dev, "WARNING: CXL adapter wide TLBIA timed out!\n"); 216f204e0b8SIan Munsie return -EBUSY; 217f204e0b8SIan Munsie } 218f204e0b8SIan Munsie cpu_relax(); 219f204e0b8SIan Munsie } 220f204e0b8SIan Munsie 221f204e0b8SIan Munsie cxl_p1_write(adapter, CXL_PSL_SLBIA, CXL_TLB_SLB_IQ_ALL); 222f204e0b8SIan Munsie while (cxl_p1_read(adapter, CXL_PSL_SLBIA) & CXL_TLB_SLB_P) { 223f204e0b8SIan Munsie if (time_after_eq(jiffies, timeout)) { 224f204e0b8SIan Munsie dev_warn(&adapter->dev, "WARNING: CXL adapter wide SLBIA timed out!\n"); 225f204e0b8SIan Munsie return -EBUSY; 226f204e0b8SIan Munsie } 227f204e0b8SIan Munsie cpu_relax(); 228f204e0b8SIan Munsie } 229f204e0b8SIan Munsie return 0; 230f204e0b8SIan Munsie } 231f204e0b8SIan Munsie 232f204e0b8SIan Munsie int cxl_afu_slbia(struct cxl_afu *afu) 233f204e0b8SIan Munsie { 234f204e0b8SIan Munsie unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); 235f204e0b8SIan Munsie 236f204e0b8SIan Munsie pr_devel("cxl_afu_slbia issuing SLBIA command\n"); 237f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_SLBIA_An, CXL_TLB_SLB_IQ_ALL); 238f204e0b8SIan Munsie while (cxl_p2n_read(afu, CXL_SLBIA_An) & CXL_TLB_SLB_P) { 239f204e0b8SIan Munsie if (time_after_eq(jiffies, timeout)) { 240f204e0b8SIan Munsie dev_warn(&afu->dev, "WARNING: CXL AFU SLBIA timed out!\n"); 241f204e0b8SIan Munsie return -EBUSY; 242f204e0b8SIan Munsie } 243f204e0b8SIan Munsie cpu_relax(); 244f204e0b8SIan Munsie } 245f204e0b8SIan Munsie return 0; 246f204e0b8SIan Munsie } 247f204e0b8SIan Munsie 248f204e0b8SIan Munsie static int cxl_write_sstp(struct cxl_afu *afu, u64 sstp0, u64 sstp1) 249f204e0b8SIan Munsie { 250f204e0b8SIan Munsie int rc; 251f204e0b8SIan Munsie 252f204e0b8SIan Munsie /* 1. Disable SSTP by writing 0 to SSTP1[V] */ 253f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_SSTP1_An, 0); 254f204e0b8SIan Munsie 255f204e0b8SIan Munsie /* 2. Invalidate all SLB entries */ 256f204e0b8SIan Munsie if ((rc = cxl_afu_slbia(afu))) 257f204e0b8SIan Munsie return rc; 258f204e0b8SIan Munsie 259f204e0b8SIan Munsie /* 3. Set SSTP0_An */ 260f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_SSTP0_An, sstp0); 261f204e0b8SIan Munsie 262f204e0b8SIan Munsie /* 4. Set SSTP1_An */ 263f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_SSTP1_An, sstp1); 264f204e0b8SIan Munsie 265f204e0b8SIan Munsie return 0; 266f204e0b8SIan Munsie } 267f204e0b8SIan Munsie 268f204e0b8SIan Munsie /* Using per slice version may improve performance here. (ie. SLBIA_An) */ 269f204e0b8SIan Munsie static void slb_invalid(struct cxl_context *ctx) 270f204e0b8SIan Munsie { 271f204e0b8SIan Munsie struct cxl *adapter = ctx->afu->adapter; 272f204e0b8SIan Munsie u64 slbia; 273f204e0b8SIan Munsie 274f204e0b8SIan Munsie WARN_ON(!mutex_is_locked(&ctx->afu->spa_mutex)); 275f204e0b8SIan Munsie 276f204e0b8SIan Munsie cxl_p1_write(adapter, CXL_PSL_LBISEL, 277f204e0b8SIan Munsie ((u64)be32_to_cpu(ctx->elem->common.pid) << 32) | 278f204e0b8SIan Munsie be32_to_cpu(ctx->elem->lpid)); 279f204e0b8SIan Munsie cxl_p1_write(adapter, CXL_PSL_SLBIA, CXL_TLB_SLB_IQ_LPIDPID); 280f204e0b8SIan Munsie 281f204e0b8SIan Munsie while (1) { 282f204e0b8SIan Munsie slbia = cxl_p1_read(adapter, CXL_PSL_SLBIA); 283f204e0b8SIan Munsie if (!(slbia & CXL_TLB_SLB_P)) 284f204e0b8SIan Munsie break; 285f204e0b8SIan Munsie cpu_relax(); 286f204e0b8SIan Munsie } 287f204e0b8SIan Munsie } 288f204e0b8SIan Munsie 289f204e0b8SIan Munsie static int do_process_element_cmd(struct cxl_context *ctx, 290f204e0b8SIan Munsie u64 cmd, u64 pe_state) 291f204e0b8SIan Munsie { 292f204e0b8SIan Munsie u64 state; 293a98e6e9fSIan Munsie unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); 2949bcf28cdSIan Munsie int rc = 0; 2959bcf28cdSIan Munsie 2969bcf28cdSIan Munsie trace_cxl_llcmd(ctx, cmd); 297f204e0b8SIan Munsie 298f204e0b8SIan Munsie WARN_ON(!ctx->afu->enabled); 299f204e0b8SIan Munsie 300f204e0b8SIan Munsie ctx->elem->software_state = cpu_to_be32(pe_state); 301f204e0b8SIan Munsie smp_wmb(); 302f204e0b8SIan Munsie *(ctx->afu->sw_command_status) = cpu_to_be64(cmd | 0 | ctx->pe); 303f204e0b8SIan Munsie smp_mb(); 304f204e0b8SIan Munsie cxl_p1n_write(ctx->afu, CXL_PSL_LLCMD_An, cmd | ctx->pe); 305f204e0b8SIan Munsie while (1) { 306a98e6e9fSIan Munsie if (time_after_eq(jiffies, timeout)) { 307a98e6e9fSIan Munsie dev_warn(&ctx->afu->dev, "WARNING: Process Element Command timed out!\n"); 3089bcf28cdSIan Munsie rc = -EBUSY; 3099bcf28cdSIan Munsie goto out; 310a98e6e9fSIan Munsie } 311f204e0b8SIan Munsie state = be64_to_cpup(ctx->afu->sw_command_status); 312f204e0b8SIan Munsie if (state == ~0ULL) { 313f204e0b8SIan Munsie pr_err("cxl: Error adding process element to AFU\n"); 3149bcf28cdSIan Munsie rc = -1; 3159bcf28cdSIan Munsie goto out; 316f204e0b8SIan Munsie } 317f204e0b8SIan Munsie if ((state & (CXL_SPA_SW_CMD_MASK | CXL_SPA_SW_STATE_MASK | CXL_SPA_SW_LINK_MASK)) == 318f204e0b8SIan Munsie (cmd | (cmd >> 16) | ctx->pe)) 319f204e0b8SIan Munsie break; 320f204e0b8SIan Munsie /* 321f204e0b8SIan Munsie * The command won't finish in the PSL if there are 322f204e0b8SIan Munsie * outstanding DSIs. Hence we need to yield here in 323f204e0b8SIan Munsie * case there are outstanding DSIs that we need to 324f204e0b8SIan Munsie * service. Tuning possiblity: we could wait for a 325f204e0b8SIan Munsie * while before sched 326f204e0b8SIan Munsie */ 327f204e0b8SIan Munsie schedule(); 328f204e0b8SIan Munsie 329f204e0b8SIan Munsie } 3309bcf28cdSIan Munsie out: 3319bcf28cdSIan Munsie trace_cxl_llcmd_done(ctx, cmd, rc); 3329bcf28cdSIan Munsie return rc; 333f204e0b8SIan Munsie } 334f204e0b8SIan Munsie 335f204e0b8SIan Munsie static int add_process_element(struct cxl_context *ctx) 336f204e0b8SIan Munsie { 337f204e0b8SIan Munsie int rc = 0; 338f204e0b8SIan Munsie 339f204e0b8SIan Munsie mutex_lock(&ctx->afu->spa_mutex); 340f204e0b8SIan Munsie pr_devel("%s Adding pe: %i started\n", __func__, ctx->pe); 341f204e0b8SIan Munsie if (!(rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_ADD, CXL_PE_SOFTWARE_STATE_V))) 342f204e0b8SIan Munsie ctx->pe_inserted = true; 343f204e0b8SIan Munsie pr_devel("%s Adding pe: %i finished\n", __func__, ctx->pe); 344f204e0b8SIan Munsie mutex_unlock(&ctx->afu->spa_mutex); 345f204e0b8SIan Munsie return rc; 346f204e0b8SIan Munsie } 347f204e0b8SIan Munsie 348f204e0b8SIan Munsie static int terminate_process_element(struct cxl_context *ctx) 349f204e0b8SIan Munsie { 350f204e0b8SIan Munsie int rc = 0; 351f204e0b8SIan Munsie 352f204e0b8SIan Munsie /* fast path terminate if it's already invalid */ 353f204e0b8SIan Munsie if (!(ctx->elem->software_state & cpu_to_be32(CXL_PE_SOFTWARE_STATE_V))) 354f204e0b8SIan Munsie return rc; 355f204e0b8SIan Munsie 356f204e0b8SIan Munsie mutex_lock(&ctx->afu->spa_mutex); 357f204e0b8SIan Munsie pr_devel("%s Terminate pe: %i started\n", __func__, ctx->pe); 358f204e0b8SIan Munsie rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_TERMINATE, 359f204e0b8SIan Munsie CXL_PE_SOFTWARE_STATE_V | CXL_PE_SOFTWARE_STATE_T); 360f204e0b8SIan Munsie ctx->elem->software_state = 0; /* Remove Valid bit */ 361f204e0b8SIan Munsie pr_devel("%s Terminate pe: %i finished\n", __func__, ctx->pe); 362f204e0b8SIan Munsie mutex_unlock(&ctx->afu->spa_mutex); 363f204e0b8SIan Munsie return rc; 364f204e0b8SIan Munsie } 365f204e0b8SIan Munsie 366f204e0b8SIan Munsie static int remove_process_element(struct cxl_context *ctx) 367f204e0b8SIan Munsie { 368f204e0b8SIan Munsie int rc = 0; 369f204e0b8SIan Munsie 370f204e0b8SIan Munsie mutex_lock(&ctx->afu->spa_mutex); 371f204e0b8SIan Munsie pr_devel("%s Remove pe: %i started\n", __func__, ctx->pe); 372f204e0b8SIan Munsie if (!(rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_REMOVE, 0))) 373f204e0b8SIan Munsie ctx->pe_inserted = false; 374f204e0b8SIan Munsie slb_invalid(ctx); 375f204e0b8SIan Munsie pr_devel("%s Remove pe: %i finished\n", __func__, ctx->pe); 376f204e0b8SIan Munsie mutex_unlock(&ctx->afu->spa_mutex); 377f204e0b8SIan Munsie 378f204e0b8SIan Munsie return rc; 379f204e0b8SIan Munsie } 380f204e0b8SIan Munsie 381f204e0b8SIan Munsie 3821a1a94b8SMichael Neuling void cxl_assign_psn_space(struct cxl_context *ctx) 383f204e0b8SIan Munsie { 384f204e0b8SIan Munsie if (!ctx->afu->pp_size || ctx->master) { 385f204e0b8SIan Munsie ctx->psn_phys = ctx->afu->psn_phys; 386f204e0b8SIan Munsie ctx->psn_size = ctx->afu->adapter->ps_size; 387f204e0b8SIan Munsie } else { 388f204e0b8SIan Munsie ctx->psn_phys = ctx->afu->psn_phys + 389f204e0b8SIan Munsie (ctx->afu->pp_offset + ctx->afu->pp_size * ctx->pe); 390f204e0b8SIan Munsie ctx->psn_size = ctx->afu->pp_size; 391f204e0b8SIan Munsie } 392f204e0b8SIan Munsie } 393f204e0b8SIan Munsie 394f204e0b8SIan Munsie static int activate_afu_directed(struct cxl_afu *afu) 395f204e0b8SIan Munsie { 396f204e0b8SIan Munsie int rc; 397f204e0b8SIan Munsie 398f204e0b8SIan Munsie dev_info(&afu->dev, "Activating AFU directed mode\n"); 399f204e0b8SIan Munsie 400f204e0b8SIan Munsie if (alloc_spa(afu)) 401f204e0b8SIan Munsie return -ENOMEM; 402f204e0b8SIan Munsie 403f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_SCNTL_An, CXL_PSL_SCNTL_An_PM_AFU); 404f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_AMOR_An, 0xFFFFFFFFFFFFFFFFULL); 405f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_ID_An, CXL_PSL_ID_An_F | CXL_PSL_ID_An_L); 406f204e0b8SIan Munsie 407f204e0b8SIan Munsie afu->current_mode = CXL_MODE_DIRECTED; 408f204e0b8SIan Munsie afu->num_procs = afu->max_procs_virtualised; 409f204e0b8SIan Munsie 410f204e0b8SIan Munsie if ((rc = cxl_chardev_m_afu_add(afu))) 411f204e0b8SIan Munsie return rc; 412f204e0b8SIan Munsie 413f204e0b8SIan Munsie if ((rc = cxl_sysfs_afu_m_add(afu))) 414f204e0b8SIan Munsie goto err; 415f204e0b8SIan Munsie 416f204e0b8SIan Munsie if ((rc = cxl_chardev_s_afu_add(afu))) 417f204e0b8SIan Munsie goto err1; 418f204e0b8SIan Munsie 419f204e0b8SIan Munsie return 0; 420f204e0b8SIan Munsie err1: 421f204e0b8SIan Munsie cxl_sysfs_afu_m_remove(afu); 422f204e0b8SIan Munsie err: 423f204e0b8SIan Munsie cxl_chardev_afu_remove(afu); 424f204e0b8SIan Munsie return rc; 425f204e0b8SIan Munsie } 426f204e0b8SIan Munsie 427f204e0b8SIan Munsie #ifdef CONFIG_CPU_LITTLE_ENDIAN 428f204e0b8SIan Munsie #define set_endian(sr) ((sr) |= CXL_PSL_SR_An_LE) 429f204e0b8SIan Munsie #else 430f204e0b8SIan Munsie #define set_endian(sr) ((sr) &= ~(CXL_PSL_SR_An_LE)) 431f204e0b8SIan Munsie #endif 432f204e0b8SIan Munsie 433f204e0b8SIan Munsie static int attach_afu_directed(struct cxl_context *ctx, u64 wed, u64 amr) 434f204e0b8SIan Munsie { 435f204e0b8SIan Munsie u64 sr; 436f204e0b8SIan Munsie int r, result; 437f204e0b8SIan Munsie 4381a1a94b8SMichael Neuling cxl_assign_psn_space(ctx); 439f204e0b8SIan Munsie 440f204e0b8SIan Munsie ctx->elem->ctxtime = 0; /* disable */ 441f204e0b8SIan Munsie ctx->elem->lpid = cpu_to_be32(mfspr(SPRN_LPID)); 442f204e0b8SIan Munsie ctx->elem->haurp = 0; /* disable */ 443f204e0b8SIan Munsie ctx->elem->sdr = cpu_to_be64(mfspr(SPRN_SDR1)); 444f204e0b8SIan Munsie 4455100a9d6SIan Munsie sr = 0; 446f204e0b8SIan Munsie if (ctx->master) 447f204e0b8SIan Munsie sr |= CXL_PSL_SR_An_MP; 448f204e0b8SIan Munsie if (mfspr(SPRN_LPCR) & LPCR_TC) 449f204e0b8SIan Munsie sr |= CXL_PSL_SR_An_TC; 450f204e0b8SIan Munsie /* HV=0, PR=1, R=1 for userspace 451f204e0b8SIan Munsie * For kernel contexts: this would need to change 452f204e0b8SIan Munsie */ 453f204e0b8SIan Munsie sr |= CXL_PSL_SR_An_PR | CXL_PSL_SR_An_R; 454f204e0b8SIan Munsie set_endian(sr); 455f204e0b8SIan Munsie sr &= ~(CXL_PSL_SR_An_HV); 456f204e0b8SIan Munsie if (!test_tsk_thread_flag(current, TIF_32BIT)) 457f204e0b8SIan Munsie sr |= CXL_PSL_SR_An_SF; 458f204e0b8SIan Munsie ctx->elem->common.pid = cpu_to_be32(current->pid); 459f204e0b8SIan Munsie ctx->elem->common.tid = 0; 460f204e0b8SIan Munsie ctx->elem->sr = cpu_to_be64(sr); 461f204e0b8SIan Munsie 462f204e0b8SIan Munsie ctx->elem->common.csrp = 0; /* disable */ 463f204e0b8SIan Munsie ctx->elem->common.aurp0 = 0; /* disable */ 464f204e0b8SIan Munsie ctx->elem->common.aurp1 = 0; /* disable */ 465f204e0b8SIan Munsie 466f204e0b8SIan Munsie cxl_prefault(ctx, wed); 467f204e0b8SIan Munsie 468f204e0b8SIan Munsie ctx->elem->common.sstp0 = cpu_to_be64(ctx->sstp0); 469f204e0b8SIan Munsie ctx->elem->common.sstp1 = cpu_to_be64(ctx->sstp1); 470f204e0b8SIan Munsie 471f204e0b8SIan Munsie for (r = 0; r < CXL_IRQ_RANGES; r++) { 472f204e0b8SIan Munsie ctx->elem->ivte_offsets[r] = cpu_to_be16(ctx->irqs.offset[r]); 473f204e0b8SIan Munsie ctx->elem->ivte_ranges[r] = cpu_to_be16(ctx->irqs.range[r]); 474f204e0b8SIan Munsie } 475f204e0b8SIan Munsie 476f204e0b8SIan Munsie ctx->elem->common.amr = cpu_to_be64(amr); 477f204e0b8SIan Munsie ctx->elem->common.wed = cpu_to_be64(wed); 478f204e0b8SIan Munsie 479f204e0b8SIan Munsie /* first guy needs to enable */ 4801a1a94b8SMichael Neuling if ((result = cxl_afu_check_and_enable(ctx->afu))) 481f204e0b8SIan Munsie return result; 482f204e0b8SIan Munsie 483f204e0b8SIan Munsie add_process_element(ctx); 484f204e0b8SIan Munsie 485f204e0b8SIan Munsie return 0; 486f204e0b8SIan Munsie } 487f204e0b8SIan Munsie 488f204e0b8SIan Munsie static int deactivate_afu_directed(struct cxl_afu *afu) 489f204e0b8SIan Munsie { 490f204e0b8SIan Munsie dev_info(&afu->dev, "Deactivating AFU directed mode\n"); 491f204e0b8SIan Munsie 492f204e0b8SIan Munsie afu->current_mode = 0; 493f204e0b8SIan Munsie afu->num_procs = 0; 494f204e0b8SIan Munsie 495f204e0b8SIan Munsie cxl_sysfs_afu_m_remove(afu); 496f204e0b8SIan Munsie cxl_chardev_afu_remove(afu); 497f204e0b8SIan Munsie 498b12994fbSMichael Neuling __cxl_afu_reset(afu); 499f204e0b8SIan Munsie cxl_afu_disable(afu); 500f204e0b8SIan Munsie cxl_psl_purge(afu); 501f204e0b8SIan Munsie 502f204e0b8SIan Munsie release_spa(afu); 503f204e0b8SIan Munsie 504f204e0b8SIan Munsie return 0; 505f204e0b8SIan Munsie } 506f204e0b8SIan Munsie 507f204e0b8SIan Munsie static int activate_dedicated_process(struct cxl_afu *afu) 508f204e0b8SIan Munsie { 509f204e0b8SIan Munsie dev_info(&afu->dev, "Activating dedicated process mode\n"); 510f204e0b8SIan Munsie 511f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_SCNTL_An, CXL_PSL_SCNTL_An_PM_Process); 512f204e0b8SIan Munsie 513f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_CtxTime_An, 0); /* disable */ 514f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_SPAP_An, 0); /* disable */ 515f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_AMOR_An, 0xFFFFFFFFFFFFFFFFULL); 516f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_LPID_An, mfspr(SPRN_LPID)); 517f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_HAURP_An, 0); /* disable */ 518f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_SDR_An, mfspr(SPRN_SDR1)); 519f204e0b8SIan Munsie 520f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_CSRP_An, 0); /* disable */ 521f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_AURP0_An, 0); /* disable */ 522f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_AURP1_An, 0); /* disable */ 523f204e0b8SIan Munsie 524f204e0b8SIan Munsie afu->current_mode = CXL_MODE_DEDICATED; 525f204e0b8SIan Munsie afu->num_procs = 1; 526f204e0b8SIan Munsie 527f204e0b8SIan Munsie return cxl_chardev_d_afu_add(afu); 528f204e0b8SIan Munsie } 529f204e0b8SIan Munsie 530f204e0b8SIan Munsie static int attach_dedicated(struct cxl_context *ctx, u64 wed, u64 amr) 531f204e0b8SIan Munsie { 532f204e0b8SIan Munsie struct cxl_afu *afu = ctx->afu; 533f204e0b8SIan Munsie u64 sr; 534f204e0b8SIan Munsie int rc; 535f204e0b8SIan Munsie 5365100a9d6SIan Munsie sr = 0; 537f204e0b8SIan Munsie set_endian(sr); 538f204e0b8SIan Munsie if (ctx->master) 539f204e0b8SIan Munsie sr |= CXL_PSL_SR_An_MP; 540f204e0b8SIan Munsie if (mfspr(SPRN_LPCR) & LPCR_TC) 541f204e0b8SIan Munsie sr |= CXL_PSL_SR_An_TC; 542f204e0b8SIan Munsie sr |= CXL_PSL_SR_An_PR | CXL_PSL_SR_An_R; 543f204e0b8SIan Munsie if (!test_tsk_thread_flag(current, TIF_32BIT)) 544f204e0b8SIan Munsie sr |= CXL_PSL_SR_An_SF; 545f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_PSL_PID_TID_An, (u64)current->pid << 32); 546f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_SR_An, sr); 547f204e0b8SIan Munsie 548f204e0b8SIan Munsie if ((rc = cxl_write_sstp(afu, ctx->sstp0, ctx->sstp1))) 549f204e0b8SIan Munsie return rc; 550f204e0b8SIan Munsie 551f204e0b8SIan Munsie cxl_prefault(ctx, wed); 552f204e0b8SIan Munsie 553f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_IVTE_Offset_An, 554f204e0b8SIan Munsie (((u64)ctx->irqs.offset[0] & 0xffff) << 48) | 555f204e0b8SIan Munsie (((u64)ctx->irqs.offset[1] & 0xffff) << 32) | 556f204e0b8SIan Munsie (((u64)ctx->irqs.offset[2] & 0xffff) << 16) | 557f204e0b8SIan Munsie ((u64)ctx->irqs.offset[3] & 0xffff)); 558f204e0b8SIan Munsie cxl_p1n_write(afu, CXL_PSL_IVTE_Limit_An, (u64) 559f204e0b8SIan Munsie (((u64)ctx->irqs.range[0] & 0xffff) << 48) | 560f204e0b8SIan Munsie (((u64)ctx->irqs.range[1] & 0xffff) << 32) | 561f204e0b8SIan Munsie (((u64)ctx->irqs.range[2] & 0xffff) << 16) | 562f204e0b8SIan Munsie ((u64)ctx->irqs.range[3] & 0xffff)); 563f204e0b8SIan Munsie 564f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_PSL_AMR_An, amr); 565f204e0b8SIan Munsie 566f204e0b8SIan Munsie /* master only context for dedicated */ 5671a1a94b8SMichael Neuling cxl_assign_psn_space(ctx); 568f204e0b8SIan Munsie 569b12994fbSMichael Neuling if ((rc = __cxl_afu_reset(afu))) 570f204e0b8SIan Munsie return rc; 571f204e0b8SIan Munsie 572f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_PSL_WED_An, wed); 573f204e0b8SIan Munsie 574f204e0b8SIan Munsie return afu_enable(afu); 575f204e0b8SIan Munsie } 576f204e0b8SIan Munsie 577f204e0b8SIan Munsie static int deactivate_dedicated_process(struct cxl_afu *afu) 578f204e0b8SIan Munsie { 579f204e0b8SIan Munsie dev_info(&afu->dev, "Deactivating dedicated process mode\n"); 580f204e0b8SIan Munsie 581f204e0b8SIan Munsie afu->current_mode = 0; 582f204e0b8SIan Munsie afu->num_procs = 0; 583f204e0b8SIan Munsie 584f204e0b8SIan Munsie cxl_chardev_afu_remove(afu); 585f204e0b8SIan Munsie 586f204e0b8SIan Munsie return 0; 587f204e0b8SIan Munsie } 588f204e0b8SIan Munsie 589f204e0b8SIan Munsie int _cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode) 590f204e0b8SIan Munsie { 591f204e0b8SIan Munsie if (mode == CXL_MODE_DIRECTED) 592f204e0b8SIan Munsie return deactivate_afu_directed(afu); 593f204e0b8SIan Munsie if (mode == CXL_MODE_DEDICATED) 594f204e0b8SIan Munsie return deactivate_dedicated_process(afu); 595f204e0b8SIan Munsie return 0; 596f204e0b8SIan Munsie } 597f204e0b8SIan Munsie 598f204e0b8SIan Munsie int cxl_afu_deactivate_mode(struct cxl_afu *afu) 599f204e0b8SIan Munsie { 600f204e0b8SIan Munsie return _cxl_afu_deactivate_mode(afu, afu->current_mode); 601f204e0b8SIan Munsie } 602f204e0b8SIan Munsie 603f204e0b8SIan Munsie int cxl_afu_activate_mode(struct cxl_afu *afu, int mode) 604f204e0b8SIan Munsie { 605f204e0b8SIan Munsie if (!mode) 606f204e0b8SIan Munsie return 0; 607f204e0b8SIan Munsie if (!(mode & afu->modes_supported)) 608f204e0b8SIan Munsie return -EINVAL; 609f204e0b8SIan Munsie 610f204e0b8SIan Munsie if (mode == CXL_MODE_DIRECTED) 611f204e0b8SIan Munsie return activate_afu_directed(afu); 612f204e0b8SIan Munsie if (mode == CXL_MODE_DEDICATED) 613f204e0b8SIan Munsie return activate_dedicated_process(afu); 614f204e0b8SIan Munsie 615f204e0b8SIan Munsie return -EINVAL; 616f204e0b8SIan Munsie } 617f204e0b8SIan Munsie 618f204e0b8SIan Munsie int cxl_attach_process(struct cxl_context *ctx, bool kernel, u64 wed, u64 amr) 619f204e0b8SIan Munsie { 620f204e0b8SIan Munsie ctx->kernel = kernel; 621f204e0b8SIan Munsie if (ctx->afu->current_mode == CXL_MODE_DIRECTED) 622f204e0b8SIan Munsie return attach_afu_directed(ctx, wed, amr); 623f204e0b8SIan Munsie 624f204e0b8SIan Munsie if (ctx->afu->current_mode == CXL_MODE_DEDICATED) 625f204e0b8SIan Munsie return attach_dedicated(ctx, wed, amr); 626f204e0b8SIan Munsie 627f204e0b8SIan Munsie return -EINVAL; 628f204e0b8SIan Munsie } 629f204e0b8SIan Munsie 630f204e0b8SIan Munsie static inline int detach_process_native_dedicated(struct cxl_context *ctx) 631f204e0b8SIan Munsie { 632b12994fbSMichael Neuling __cxl_afu_reset(ctx->afu); 633f204e0b8SIan Munsie cxl_afu_disable(ctx->afu); 634f204e0b8SIan Munsie cxl_psl_purge(ctx->afu); 635f204e0b8SIan Munsie return 0; 636f204e0b8SIan Munsie } 637f204e0b8SIan Munsie 638f204e0b8SIan Munsie static inline int detach_process_native_afu_directed(struct cxl_context *ctx) 639f204e0b8SIan Munsie { 640f204e0b8SIan Munsie if (!ctx->pe_inserted) 641f204e0b8SIan Munsie return 0; 642f204e0b8SIan Munsie if (terminate_process_element(ctx)) 643f204e0b8SIan Munsie return -1; 644f204e0b8SIan Munsie if (remove_process_element(ctx)) 645f204e0b8SIan Munsie return -1; 646f204e0b8SIan Munsie 647f204e0b8SIan Munsie return 0; 648f204e0b8SIan Munsie } 649f204e0b8SIan Munsie 650f204e0b8SIan Munsie int cxl_detach_process(struct cxl_context *ctx) 651f204e0b8SIan Munsie { 6529bcf28cdSIan Munsie trace_cxl_detach(ctx); 6539bcf28cdSIan Munsie 654f204e0b8SIan Munsie if (ctx->afu->current_mode == CXL_MODE_DEDICATED) 655f204e0b8SIan Munsie return detach_process_native_dedicated(ctx); 656f204e0b8SIan Munsie 657f204e0b8SIan Munsie return detach_process_native_afu_directed(ctx); 658f204e0b8SIan Munsie } 659f204e0b8SIan Munsie 660bc78b05bSIan Munsie int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info) 661f204e0b8SIan Munsie { 662f204e0b8SIan Munsie u64 pidtid; 663f204e0b8SIan Munsie 664bc78b05bSIan Munsie info->dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); 665bc78b05bSIan Munsie info->dar = cxl_p2n_read(afu, CXL_PSL_DAR_An); 666bc78b05bSIan Munsie info->dsr = cxl_p2n_read(afu, CXL_PSL_DSR_An); 667bc78b05bSIan Munsie pidtid = cxl_p2n_read(afu, CXL_PSL_PID_TID_An); 668f204e0b8SIan Munsie info->pid = pidtid >> 32; 669f204e0b8SIan Munsie info->tid = pidtid & 0xffffffff; 670bc78b05bSIan Munsie info->afu_err = cxl_p2n_read(afu, CXL_AFU_ERR_An); 671bc78b05bSIan Munsie info->errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An); 672f204e0b8SIan Munsie 673f204e0b8SIan Munsie return 0; 674f204e0b8SIan Munsie } 675f204e0b8SIan Munsie 676f204e0b8SIan Munsie static void recover_psl_err(struct cxl_afu *afu, u64 errstat) 677f204e0b8SIan Munsie { 678f204e0b8SIan Munsie u64 dsisr; 679f204e0b8SIan Munsie 680f204e0b8SIan Munsie pr_devel("RECOVERING FROM PSL ERROR... (0x%.16llx)\n", errstat); 681f204e0b8SIan Munsie 682f204e0b8SIan Munsie /* Clear PSL_DSISR[PE] */ 683f204e0b8SIan Munsie dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); 684f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_PSL_DSISR_An, dsisr & ~CXL_PSL_DSISR_An_PE); 685f204e0b8SIan Munsie 686f204e0b8SIan Munsie /* Write 1s to clear error status bits */ 687f204e0b8SIan Munsie cxl_p2n_write(afu, CXL_PSL_ErrStat_An, errstat); 688f204e0b8SIan Munsie } 689f204e0b8SIan Munsie 690f204e0b8SIan Munsie int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask) 691f204e0b8SIan Munsie { 6929bcf28cdSIan Munsie trace_cxl_psl_irq_ack(ctx, tfc); 693f204e0b8SIan Munsie if (tfc) 694f204e0b8SIan Munsie cxl_p2n_write(ctx->afu, CXL_PSL_TFC_An, tfc); 695f204e0b8SIan Munsie if (psl_reset_mask) 696f204e0b8SIan Munsie recover_psl_err(ctx->afu, psl_reset_mask); 697f204e0b8SIan Munsie 698f204e0b8SIan Munsie return 0; 699f204e0b8SIan Munsie } 700f204e0b8SIan Munsie 701f204e0b8SIan Munsie int cxl_check_error(struct cxl_afu *afu) 702f204e0b8SIan Munsie { 703f204e0b8SIan Munsie return (cxl_p1n_read(afu, CXL_PSL_SCNTL_An) == ~0ULL); 704f204e0b8SIan Munsie } 705