diff options
Diffstat (limited to 'drivers/misc/cxl/native.c')
| -rw-r--r-- | drivers/misc/cxl/native.c | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c index f2b37b41a0da..29185fc61276 100644 --- a/drivers/misc/cxl/native.c +++ b/drivers/misc/cxl/native.c | |||
| @@ -18,24 +18,28 @@ | |||
| 18 | #include <misc/cxl.h> | 18 | #include <misc/cxl.h> |
| 19 | 19 | ||
| 20 | #include "cxl.h" | 20 | #include "cxl.h" |
| 21 | #include "trace.h" | ||
| 21 | 22 | ||
| 22 | static int afu_control(struct cxl_afu *afu, u64 command, | 23 | static int afu_control(struct cxl_afu *afu, u64 command, |
| 23 | u64 result, u64 mask, bool enabled) | 24 | u64 result, u64 mask, bool enabled) |
| 24 | { | 25 | { |
| 25 | u64 AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); | 26 | u64 AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); |
| 26 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); | 27 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); |
| 28 | int rc = 0; | ||
| 27 | 29 | ||
| 28 | spin_lock(&afu->afu_cntl_lock); | 30 | spin_lock(&afu->afu_cntl_lock); |
| 29 | pr_devel("AFU command starting: %llx\n", command); | 31 | pr_devel("AFU command starting: %llx\n", command); |
| 30 | 32 | ||
| 33 | trace_cxl_afu_ctrl(afu, command); | ||
| 34 | |||
| 31 | cxl_p2n_write(afu, CXL_AFU_Cntl_An, AFU_Cntl | command); | 35 | cxl_p2n_write(afu, CXL_AFU_Cntl_An, AFU_Cntl | command); |
| 32 | 36 | ||
| 33 | AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); | 37 | AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); |
| 34 | while ((AFU_Cntl & mask) != result) { | 38 | while ((AFU_Cntl & mask) != result) { |
| 35 | if (time_after_eq(jiffies, timeout)) { | 39 | if (time_after_eq(jiffies, timeout)) { |
| 36 | dev_warn(&afu->dev, "WARNING: AFU control timed out!\n"); | 40 | dev_warn(&afu->dev, "WARNING: AFU control timed out!\n"); |
| 37 | spin_unlock(&afu->afu_cntl_lock); | 41 | rc = -EBUSY; |
| 38 | return -EBUSY; | 42 | goto out; |
| 39 | } | 43 | } |
| 40 | pr_devel_ratelimited("AFU control... (0x%.16llx)\n", | 44 | pr_devel_ratelimited("AFU control... (0x%.16llx)\n", |
| 41 | AFU_Cntl | command); | 45 | AFU_Cntl | command); |
| @@ -44,9 +48,11 @@ static int afu_control(struct cxl_afu *afu, u64 command, | |||
| 44 | }; | 48 | }; |
| 45 | pr_devel("AFU command complete: %llx\n", command); | 49 | pr_devel("AFU command complete: %llx\n", command); |
| 46 | afu->enabled = enabled; | 50 | afu->enabled = enabled; |
| 51 | out: | ||
| 52 | trace_cxl_afu_ctrl_done(afu, command, rc); | ||
| 47 | spin_unlock(&afu->afu_cntl_lock); | 53 | spin_unlock(&afu->afu_cntl_lock); |
| 48 | 54 | ||
| 49 | return 0; | 55 | return rc; |
| 50 | } | 56 | } |
| 51 | 57 | ||
| 52 | static int afu_enable(struct cxl_afu *afu) | 58 | static int afu_enable(struct cxl_afu *afu) |
| @@ -91,6 +97,9 @@ int cxl_psl_purge(struct cxl_afu *afu) | |||
| 91 | u64 dsisr, dar; | 97 | u64 dsisr, dar; |
| 92 | u64 start, end; | 98 | u64 start, end; |
| 93 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); | 99 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); |
| 100 | int rc = 0; | ||
| 101 | |||
| 102 | trace_cxl_psl_ctrl(afu, CXL_PSL_SCNTL_An_Pc); | ||
| 94 | 103 | ||
| 95 | pr_devel("PSL purge request\n"); | 104 | pr_devel("PSL purge request\n"); |
| 96 | 105 | ||
| @@ -107,7 +116,8 @@ int cxl_psl_purge(struct cxl_afu *afu) | |||
| 107 | == CXL_PSL_SCNTL_An_Ps_Pending) { | 116 | == CXL_PSL_SCNTL_An_Ps_Pending) { |
| 108 | if (time_after_eq(jiffies, timeout)) { | 117 | if (time_after_eq(jiffies, timeout)) { |
| 109 | dev_warn(&afu->dev, "WARNING: PSL Purge timed out!\n"); | 118 | dev_warn(&afu->dev, "WARNING: PSL Purge timed out!\n"); |
| 110 | return -EBUSY; | 119 | rc = -EBUSY; |
| 120 | goto out; | ||
| 111 | } | 121 | } |
| 112 | dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); | 122 | dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); |
| 113 | pr_devel_ratelimited("PSL purging... PSL_CNTL: 0x%.16llx PSL_DSISR: 0x%.16llx\n", PSL_CNTL, dsisr); | 123 | pr_devel_ratelimited("PSL purging... PSL_CNTL: 0x%.16llx PSL_DSISR: 0x%.16llx\n", PSL_CNTL, dsisr); |
| @@ -128,7 +138,9 @@ int cxl_psl_purge(struct cxl_afu *afu) | |||
| 128 | 138 | ||
| 129 | cxl_p1n_write(afu, CXL_PSL_SCNTL_An, | 139 | cxl_p1n_write(afu, CXL_PSL_SCNTL_An, |
| 130 | PSL_CNTL & ~CXL_PSL_SCNTL_An_Pc); | 140 | PSL_CNTL & ~CXL_PSL_SCNTL_An_Pc); |
| 131 | return 0; | 141 | out: |
| 142 | trace_cxl_psl_ctrl_done(afu, CXL_PSL_SCNTL_An_Pc, rc); | ||
| 143 | return rc; | ||
| 132 | } | 144 | } |
| 133 | 145 | ||
| 134 | static int spa_max_procs(int spa_size) | 146 | static int spa_max_procs(int spa_size) |
| @@ -185,6 +197,7 @@ static int alloc_spa(struct cxl_afu *afu) | |||
| 185 | 197 | ||
| 186 | static void release_spa(struct cxl_afu *afu) | 198 | static void release_spa(struct cxl_afu *afu) |
| 187 | { | 199 | { |
| 200 | cxl_p1n_write(afu, CXL_PSL_SPAP_An, 0); | ||
| 188 | free_pages((unsigned long) afu->spa, afu->spa_order); | 201 | free_pages((unsigned long) afu->spa, afu->spa_order); |
| 189 | } | 202 | } |
| 190 | 203 | ||
| @@ -278,6 +291,9 @@ static int do_process_element_cmd(struct cxl_context *ctx, | |||
| 278 | { | 291 | { |
| 279 | u64 state; | 292 | u64 state; |
| 280 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); | 293 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); |
| 294 | int rc = 0; | ||
| 295 | |||
| 296 | trace_cxl_llcmd(ctx, cmd); | ||
| 281 | 297 | ||
| 282 | WARN_ON(!ctx->afu->enabled); | 298 | WARN_ON(!ctx->afu->enabled); |
| 283 | 299 | ||
| @@ -289,12 +305,14 @@ static int do_process_element_cmd(struct cxl_context *ctx, | |||
| 289 | while (1) { | 305 | while (1) { |
| 290 | if (time_after_eq(jiffies, timeout)) { | 306 | if (time_after_eq(jiffies, timeout)) { |
| 291 | dev_warn(&ctx->afu->dev, "WARNING: Process Element Command timed out!\n"); | 307 | dev_warn(&ctx->afu->dev, "WARNING: Process Element Command timed out!\n"); |
| 292 | return -EBUSY; | 308 | rc = -EBUSY; |
| 309 | goto out; | ||
| 293 | } | 310 | } |
| 294 | state = be64_to_cpup(ctx->afu->sw_command_status); | 311 | state = be64_to_cpup(ctx->afu->sw_command_status); |
| 295 | if (state == ~0ULL) { | 312 | if (state == ~0ULL) { |
| 296 | pr_err("cxl: Error adding process element to AFU\n"); | 313 | pr_err("cxl: Error adding process element to AFU\n"); |
| 297 | return -1; | 314 | rc = -1; |
| 315 | goto out; | ||
| 298 | } | 316 | } |
| 299 | if ((state & (CXL_SPA_SW_CMD_MASK | CXL_SPA_SW_STATE_MASK | CXL_SPA_SW_LINK_MASK)) == | 317 | if ((state & (CXL_SPA_SW_CMD_MASK | CXL_SPA_SW_STATE_MASK | CXL_SPA_SW_LINK_MASK)) == |
| 300 | (cmd | (cmd >> 16) | ctx->pe)) | 318 | (cmd | (cmd >> 16) | ctx->pe)) |
| @@ -309,7 +327,9 @@ static int do_process_element_cmd(struct cxl_context *ctx, | |||
| 309 | schedule(); | 327 | schedule(); |
| 310 | 328 | ||
| 311 | } | 329 | } |
| 312 | return 0; | 330 | out: |
| 331 | trace_cxl_llcmd_done(ctx, cmd, rc); | ||
| 332 | return rc; | ||
| 313 | } | 333 | } |
| 314 | 334 | ||
| 315 | static int add_process_element(struct cxl_context *ctx) | 335 | static int add_process_element(struct cxl_context *ctx) |
| @@ -629,6 +649,8 @@ static inline int detach_process_native_afu_directed(struct cxl_context *ctx) | |||
| 629 | 649 | ||
| 630 | int cxl_detach_process(struct cxl_context *ctx) | 650 | int cxl_detach_process(struct cxl_context *ctx) |
| 631 | { | 651 | { |
| 652 | trace_cxl_detach(ctx); | ||
| 653 | |||
| 632 | if (ctx->afu->current_mode == CXL_MODE_DEDICATED) | 654 | if (ctx->afu->current_mode == CXL_MODE_DEDICATED) |
| 633 | return detach_process_native_dedicated(ctx); | 655 | return detach_process_native_dedicated(ctx); |
| 634 | 656 | ||
| @@ -667,6 +689,7 @@ static void recover_psl_err(struct cxl_afu *afu, u64 errstat) | |||
| 667 | 689 | ||
| 668 | int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask) | 690 | int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask) |
| 669 | { | 691 | { |
| 692 | trace_cxl_psl_irq_ack(ctx, tfc); | ||
| 670 | if (tfc) | 693 | if (tfc) |
| 671 | cxl_p2n_write(ctx->afu, CXL_PSL_TFC_An, tfc); | 694 | cxl_p2n_write(ctx->afu, CXL_PSL_TFC_An, tfc); |
| 672 | if (psl_reset_mask) | 695 | if (psl_reset_mask) |
