|
14 | 14 | #include <linux/mutex.h> |
15 | 15 | #include <linux/mm.h> |
16 | 16 | #include <linux/uaccess.h> |
| 17 | +#include <linux/delay.h> |
17 | 18 | #include <asm/synch.h> |
18 | 19 | #include <misc/cxl-base.h> |
19 | 20 |
|
@@ -797,6 +798,35 @@ static irqreturn_t native_irq_multiplexed(int irq, void *data) |
797 | 798 | return fail_psl_irq(afu, &irq_info); |
798 | 799 | } |
799 | 800 |
|
| 801 | +void native_irq_wait(struct cxl_context *ctx) |
| 802 | +{ |
| 803 | + u64 dsisr; |
| 804 | + int timeout = 1000; |
| 805 | + int ph; |
| 806 | + |
| 807 | + /* |
| 808 | + * Wait until no further interrupts are presented by the PSL |
| 809 | + * for this context. |
| 810 | + */ |
| 811 | + while (timeout--) { |
| 812 | + ph = cxl_p2n_read(ctx->afu, CXL_PSL_PEHandle_An) & 0xffff; |
| 813 | + if (ph != ctx->pe) |
| 814 | + return; |
| 815 | + dsisr = cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An); |
| 816 | + if ((dsisr & CXL_PSL_DSISR_PENDING) == 0) |
| 817 | + return; |
| 818 | + /* |
| 819 | + * We are waiting for the workqueue to process our |
| 820 | + * irq, so need to let that run here. |
| 821 | + */ |
| 822 | + msleep(1); |
| 823 | + } |
| 824 | + |
| 825 | + dev_warn(&ctx->afu->dev, "WARNING: waiting on DSI for PE %i" |
| 826 | + " DSISR %016llx!\n", ph, dsisr); |
| 827 | + return; |
| 828 | +} |
| 829 | + |
800 | 830 | static irqreturn_t native_slice_irq_err(int irq, void *data) |
801 | 831 | { |
802 | 832 | struct cxl_afu *afu = data; |
@@ -1076,6 +1106,7 @@ const struct cxl_backend_ops cxl_native_ops = { |
1076 | 1106 | .handle_psl_slice_error = native_handle_psl_slice_error, |
1077 | 1107 | .psl_interrupt = NULL, |
1078 | 1108 | .ack_irq = native_ack_irq, |
| 1109 | + .irq_wait = native_irq_wait, |
1079 | 1110 | .attach_process = native_attach_process, |
1080 | 1111 | .detach_process = native_detach_process, |
1081 | 1112 | .support_attributes = native_support_attributes, |
|
0 commit comments