diff options
author | Frederic Barrat <fbarrat@linux.vnet.ibm.com> | 2016-03-04 06:26:28 -0500 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2016-03-08 21:05:43 -0500 |
commit | 5be587b1110132b4f05e0bc3515a145365e910fe (patch) | |
tree | 102af0ae101eef7c75f39bb696cda28ed45c8f65 | |
parent | cca44c0192b03d179786ec34b070e7de42966cc6 (diff) |
cxl: Introduce implementation-specific API
The backend API (in cxl.h) lists some low-level functions whose
implementation is different on bare-metal and in a guest. Each
environment implements its own functions, and the common code uses
them through function pointers, defined in cxl_backend_ops
Co-authored-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
Reviewed-by: Manoj Kumar <manoj@linux.vnet.ibm.com>
Acked-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r-- | drivers/misc/cxl/api.c | 8 | ||||
-rw-r--r-- | drivers/misc/cxl/context.c | 4 | ||||
-rw-r--r-- | drivers/misc/cxl/cxl.h | 53 | ||||
-rw-r--r-- | drivers/misc/cxl/fault.c | 6 | ||||
-rw-r--r-- | drivers/misc/cxl/file.c | 15 | ||||
-rw-r--r-- | drivers/misc/cxl/irq.c | 19 | ||||
-rw-r--r-- | drivers/misc/cxl/main.c | 11 | ||||
-rw-r--r-- | drivers/misc/cxl/native.c | 135 | ||||
-rw-r--r-- | drivers/misc/cxl/pci.c | 16 | ||||
-rw-r--r-- | drivers/misc/cxl/sysfs.c | 32 | ||||
-rw-r--r-- | drivers/misc/cxl/vphb.c | 6 |
11 files changed, 185 insertions, 120 deletions
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index b45d857b0207..31eb842ee6c0 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c | |||
@@ -100,7 +100,7 @@ EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs); | |||
100 | void cxl_free_afu_irqs(struct cxl_context *ctx) | 100 | void cxl_free_afu_irqs(struct cxl_context *ctx) |
101 | { | 101 | { |
102 | afu_irq_name_free(ctx); | 102 | afu_irq_name_free(ctx); |
103 | cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter); | 103 | cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter); |
104 | } | 104 | } |
105 | EXPORT_SYMBOL_GPL(cxl_free_afu_irqs); | 105 | EXPORT_SYMBOL_GPL(cxl_free_afu_irqs); |
106 | 106 | ||
@@ -176,7 +176,7 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, | |||
176 | 176 | ||
177 | cxl_ctx_get(); | 177 | cxl_ctx_get(); |
178 | 178 | ||
179 | if ((rc = cxl_attach_process(ctx, kernel, wed , 0))) { | 179 | if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { |
180 | put_pid(ctx->pid); | 180 | put_pid(ctx->pid); |
181 | cxl_ctx_put(); | 181 | cxl_ctx_put(); |
182 | goto out; | 182 | goto out; |
@@ -342,11 +342,11 @@ int cxl_afu_reset(struct cxl_context *ctx) | |||
342 | struct cxl_afu *afu = ctx->afu; | 342 | struct cxl_afu *afu = ctx->afu; |
343 | int rc; | 343 | int rc; |
344 | 344 | ||
345 | rc = __cxl_afu_reset(afu); | 345 | rc = cxl_ops->afu_reset(afu); |
346 | if (rc) | 346 | if (rc) |
347 | return rc; | 347 | return rc; |
348 | 348 | ||
349 | return cxl_afu_check_and_enable(afu); | 349 | return cxl_ops->afu_check_and_enable(afu); |
350 | } | 350 | } |
351 | EXPORT_SYMBOL_GPL(cxl_afu_reset); | 351 | EXPORT_SYMBOL_GPL(cxl_afu_reset); |
352 | 352 | ||
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c index 262b88eac414..aa65262d4a32 100644 --- a/drivers/misc/cxl/context.c +++ b/drivers/misc/cxl/context.c | |||
@@ -214,8 +214,8 @@ int __detach_context(struct cxl_context *ctx) | |||
214 | /* Only warn if we detached while the link was OK. | 214 | /* Only warn if we detached while the link was OK. |
215 | * If detach fails when hw is down, we don't care. | 215 | * If detach fails when hw is down, we don't care. |
216 | */ | 216 | */ |
217 | WARN_ON(cxl_detach_process(ctx) && | 217 | WARN_ON(cxl_ops->detach_process(ctx) && |
218 | cxl_adapter_link_ok(ctx->afu->adapter)); | 218 | cxl_ops->link_ok(ctx->afu->adapter)); |
219 | flush_work(&ctx->fault_work); /* Only needed for dedicated process */ | 219 | flush_work(&ctx->fault_work); /* Only needed for dedicated process */ |
220 | 220 | ||
221 | /* release the reference to the group leader and mm handling pid */ | 221 | /* release the reference to the group leader and mm handling pid */ |
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index 3b824e3d68d2..8233af305f8d 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h | |||
@@ -623,11 +623,6 @@ static inline u64 cxl_p2n_read(struct cxl_afu *afu, cxl_p2n_reg_t reg) | |||
623 | return ~0ULL; | 623 | return ~0ULL; |
624 | } | 624 | } |
625 | 625 | ||
626 | u64 cxl_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off); | ||
627 | u32 cxl_afu_cr_read32(struct cxl_afu *afu, int cr, u64 off); | ||
628 | u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off); | ||
629 | u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off); | ||
630 | |||
631 | ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf, | 626 | ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf, |
632 | loff_t off, size_t count); | 627 | loff_t off, size_t count); |
633 | 628 | ||
@@ -666,10 +661,6 @@ void cxl_sysfs_afu_m_remove(struct cxl_afu *afu); | |||
666 | 661 | ||
667 | struct cxl *cxl_alloc_adapter(void); | 662 | struct cxl *cxl_alloc_adapter(void); |
668 | struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice); | 663 | struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice); |
669 | |||
670 | int cxl_afu_activate_mode(struct cxl_afu *afu, int mode); | ||
671 | int _cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode); | ||
672 | int cxl_afu_deactivate_mode(struct cxl_afu *afu); | ||
673 | int cxl_afu_select_best_mode(struct cxl_afu *afu); | 664 | int cxl_afu_select_best_mode(struct cxl_afu *afu); |
674 | 665 | ||
675 | int cxl_register_psl_irq(struct cxl_afu *afu); | 666 | int cxl_register_psl_irq(struct cxl_afu *afu); |
@@ -681,8 +672,6 @@ void cxl_release_serr_irq(struct cxl_afu *afu); | |||
681 | int afu_register_irqs(struct cxl_context *ctx, u32 count); | 672 | int afu_register_irqs(struct cxl_context *ctx, u32 count); |
682 | void afu_release_irqs(struct cxl_context *ctx, void *cookie); | 673 | void afu_release_irqs(struct cxl_context *ctx, void *cookie); |
683 | void afu_irq_name_free(struct cxl_context *ctx); | 674 | void afu_irq_name_free(struct cxl_context *ctx); |
684 | irqreturn_t handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, | ||
685 | u64 errstat); | ||
686 | 675 | ||
687 | int cxl_debugfs_init(void); | 676 | int cxl_debugfs_init(void); |
688 | void cxl_debugfs_exit(void); | 677 | void cxl_debugfs_exit(void); |
@@ -727,18 +716,10 @@ int cxl_register_one_irq(struct cxl *adapter, irq_handler_t handler, | |||
727 | void *cookie, irq_hw_number_t *dest_hwirq, | 716 | void *cookie, irq_hw_number_t *dest_hwirq, |
728 | unsigned int *dest_virq, const char *name); | 717 | unsigned int *dest_virq, const char *name); |
729 | 718 | ||
730 | int cxl_attach_process(struct cxl_context *ctx, bool kernel, u64 wed, | ||
731 | u64 amr); | ||
732 | int cxl_detach_process(struct cxl_context *ctx); | ||
733 | |||
734 | int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask); | ||
735 | |||
736 | int cxl_check_error(struct cxl_afu *afu); | 719 | int cxl_check_error(struct cxl_afu *afu); |
737 | int cxl_afu_slbia(struct cxl_afu *afu); | 720 | int cxl_afu_slbia(struct cxl_afu *afu); |
738 | int cxl_tlb_slb_invalidate(struct cxl *adapter); | 721 | int cxl_tlb_slb_invalidate(struct cxl *adapter); |
739 | int cxl_afu_disable(struct cxl_afu *afu); | 722 | int cxl_afu_disable(struct cxl_afu *afu); |
740 | int __cxl_afu_reset(struct cxl_afu *afu); | ||
741 | int cxl_afu_check_and_enable(struct cxl_afu *afu); | ||
742 | int cxl_psl_purge(struct cxl_afu *afu); | 723 | int cxl_psl_purge(struct cxl_afu *afu); |
743 | 724 | ||
744 | void cxl_stop_trace(struct cxl *cxl); | 725 | void cxl_stop_trace(struct cxl *cxl); |
@@ -757,4 +738,38 @@ unsigned int afu_poll(struct file *file, struct poll_table_struct *poll); | |||
757 | ssize_t afu_read(struct file *file, char __user *buf, size_t count, loff_t *off); | 738 | ssize_t afu_read(struct file *file, char __user *buf, size_t count, loff_t *off); |
758 | extern const struct file_operations afu_fops; | 739 | extern const struct file_operations afu_fops; |
759 | 740 | ||
741 | struct cxl_backend_ops { | ||
742 | struct module *module; | ||
743 | int (*adapter_reset)(struct cxl *adapter); | ||
744 | int (*alloc_one_irq)(struct cxl *adapter); | ||
745 | void (*release_one_irq)(struct cxl *adapter, int hwirq); | ||
746 | int (*alloc_irq_ranges)(struct cxl_irq_ranges *irqs, | ||
747 | struct cxl *adapter, unsigned int num); | ||
748 | void (*release_irq_ranges)(struct cxl_irq_ranges *irqs, | ||
749 | struct cxl *adapter); | ||
750 | int (*setup_irq)(struct cxl *adapter, unsigned int hwirq, | ||
751 | unsigned int virq); | ||
752 | irqreturn_t (*handle_psl_slice_error)(struct cxl_context *ctx, | ||
753 | u64 dsisr, u64 errstat); | ||
754 | irqreturn_t (*psl_interrupt)(int irq, void *data); | ||
755 | int (*ack_irq)(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask); | ||
756 | int (*attach_process)(struct cxl_context *ctx, bool kernel, | ||
757 | u64 wed, u64 amr); | ||
758 | int (*detach_process)(struct cxl_context *ctx); | ||
759 | bool (*link_ok)(struct cxl *cxl); | ||
760 | void (*release_afu)(struct device *dev); | ||
761 | ssize_t (*afu_read_err_buffer)(struct cxl_afu *afu, char *buf, | ||
762 | loff_t off, size_t count); | ||
763 | int (*afu_check_and_enable)(struct cxl_afu *afu); | ||
764 | int (*afu_activate_mode)(struct cxl_afu *afu, int mode); | ||
765 | int (*afu_deactivate_mode)(struct cxl_afu *afu, int mode); | ||
766 | int (*afu_reset)(struct cxl_afu *afu); | ||
767 | int (*afu_cr_read8)(struct cxl_afu *afu, int cr_idx, u64 offset, u8 *val); | ||
768 | int (*afu_cr_read16)(struct cxl_afu *afu, int cr_idx, u64 offset, u16 *val); | ||
769 | int (*afu_cr_read32)(struct cxl_afu *afu, int cr_idx, u64 offset, u32 *val); | ||
770 | int (*afu_cr_read64)(struct cxl_afu *afu, int cr_idx, u64 offset, u64 *val); | ||
771 | }; | ||
772 | extern const struct cxl_backend_ops cxl_native_ops; | ||
773 | extern const struct cxl_backend_ops *cxl_ops; | ||
774 | |||
760 | #endif | 775 | #endif |
diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c index 81c3f75b7330..ab740a19bd1e 100644 --- a/drivers/misc/cxl/fault.c +++ b/drivers/misc/cxl/fault.c | |||
@@ -101,7 +101,7 @@ static void cxl_ack_ae(struct cxl_context *ctx) | |||
101 | { | 101 | { |
102 | unsigned long flags; | 102 | unsigned long flags; |
103 | 103 | ||
104 | cxl_ack_irq(ctx, CXL_PSL_TFC_An_AE, 0); | 104 | cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_AE, 0); |
105 | 105 | ||
106 | spin_lock_irqsave(&ctx->lock, flags); | 106 | spin_lock_irqsave(&ctx->lock, flags); |
107 | ctx->pending_fault = true; | 107 | ctx->pending_fault = true; |
@@ -125,7 +125,7 @@ static int cxl_handle_segment_miss(struct cxl_context *ctx, | |||
125 | else { | 125 | else { |
126 | 126 | ||
127 | mb(); /* Order seg table write to TFC MMIO write */ | 127 | mb(); /* Order seg table write to TFC MMIO write */ |
128 | cxl_ack_irq(ctx, CXL_PSL_TFC_An_R, 0); | 128 | cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_R, 0); |
129 | } | 129 | } |
130 | 130 | ||
131 | return IRQ_HANDLED; | 131 | return IRQ_HANDLED; |
@@ -163,7 +163,7 @@ static void cxl_handle_page_fault(struct cxl_context *ctx, | |||
163 | local_irq_restore(flags); | 163 | local_irq_restore(flags); |
164 | 164 | ||
165 | pr_devel("Page fault successfully handled for pe: %i!\n", ctx->pe); | 165 | pr_devel("Page fault successfully handled for pe: %i!\n", ctx->pe); |
166 | cxl_ack_irq(ctx, CXL_PSL_TFC_An_R, 0); | 166 | cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_R, 0); |
167 | } | 167 | } |
168 | 168 | ||
169 | /* | 169 | /* |
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c index 783337d22f36..b8ce29bc52d5 100644 --- a/drivers/misc/cxl/file.c +++ b/drivers/misc/cxl/file.c | |||
@@ -79,7 +79,7 @@ static int __afu_open(struct inode *inode, struct file *file, bool master) | |||
79 | if (!afu->current_mode) | 79 | if (!afu->current_mode) |
80 | goto err_put_afu; | 80 | goto err_put_afu; |
81 | 81 | ||
82 | if (!cxl_adapter_link_ok(adapter)) { | 82 | if (!cxl_ops->link_ok(adapter)) { |
83 | rc = -EIO; | 83 | rc = -EIO; |
84 | goto err_put_afu; | 84 | goto err_put_afu; |
85 | } | 85 | } |
@@ -210,8 +210,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, | |||
210 | 210 | ||
211 | trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); | 211 | trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); |
212 | 212 | ||
213 | if ((rc = cxl_attach_process(ctx, false, work.work_element_descriptor, | 213 | if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor, |
214 | amr))) { | 214 | amr))) { |
215 | afu_release_irqs(ctx, ctx); | 215 | afu_release_irqs(ctx, ctx); |
216 | goto out; | 216 | goto out; |
217 | } | 217 | } |
@@ -222,6 +222,7 @@ out: | |||
222 | mutex_unlock(&ctx->status_mutex); | 222 | mutex_unlock(&ctx->status_mutex); |
223 | return rc; | 223 | return rc; |
224 | } | 224 | } |
225 | |||
225 | static long afu_ioctl_process_element(struct cxl_context *ctx, | 226 | static long afu_ioctl_process_element(struct cxl_context *ctx, |
226 | int __user *upe) | 227 | int __user *upe) |
227 | { | 228 | { |
@@ -259,7 +260,7 @@ long afu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
259 | if (ctx->status == CLOSED) | 260 | if (ctx->status == CLOSED) |
260 | return -EIO; | 261 | return -EIO; |
261 | 262 | ||
262 | if (!cxl_adapter_link_ok(ctx->afu->adapter)) | 263 | if (!cxl_ops->link_ok(ctx->afu->adapter)) |
263 | return -EIO; | 264 | return -EIO; |
264 | 265 | ||
265 | pr_devel("afu_ioctl\n"); | 266 | pr_devel("afu_ioctl\n"); |
@@ -289,7 +290,7 @@ int afu_mmap(struct file *file, struct vm_area_struct *vm) | |||
289 | if (ctx->status != STARTED) | 290 | if (ctx->status != STARTED) |
290 | return -EIO; | 291 | return -EIO; |
291 | 292 | ||
292 | if (!cxl_adapter_link_ok(ctx->afu->adapter)) | 293 | if (!cxl_ops->link_ok(ctx->afu->adapter)) |
293 | return -EIO; | 294 | return -EIO; |
294 | 295 | ||
295 | return cxl_context_iomap(ctx, vm); | 296 | return cxl_context_iomap(ctx, vm); |
@@ -336,7 +337,7 @@ ssize_t afu_read(struct file *file, char __user *buf, size_t count, | |||
336 | int rc; | 337 | int rc; |
337 | DEFINE_WAIT(wait); | 338 | DEFINE_WAIT(wait); |
338 | 339 | ||
339 | if (!cxl_adapter_link_ok(ctx->afu->adapter)) | 340 | if (!cxl_ops->link_ok(ctx->afu->adapter)) |
340 | return -EIO; | 341 | return -EIO; |
341 | 342 | ||
342 | if (count < CXL_READ_MIN_SIZE) | 343 | if (count < CXL_READ_MIN_SIZE) |
@@ -349,7 +350,7 @@ ssize_t afu_read(struct file *file, char __user *buf, size_t count, | |||
349 | if (ctx_event_pending(ctx)) | 350 | if (ctx_event_pending(ctx)) |
350 | break; | 351 | break; |
351 | 352 | ||
352 | if (!cxl_adapter_link_ok(ctx->afu->adapter)) { | 353 | if (!cxl_ops->link_ok(ctx->afu->adapter)) { |
353 | rc = -EIO; | 354 | rc = -EIO; |
354 | goto out; | 355 | goto out; |
355 | } | 356 | } |
diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c index 16fd67ffb5ef..56ad301007b7 100644 --- a/drivers/misc/cxl/irq.c +++ b/drivers/misc/cxl/irq.c | |||
@@ -79,7 +79,8 @@ irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info) | |||
79 | if (dsisr & CXL_PSL_DSISR_An_UR) | 79 | if (dsisr & CXL_PSL_DSISR_An_UR) |
80 | pr_devel("CXL interrupt: AURP PTE not found\n"); | 80 | pr_devel("CXL interrupt: AURP PTE not found\n"); |
81 | if (dsisr & CXL_PSL_DSISR_An_PE) | 81 | if (dsisr & CXL_PSL_DSISR_An_PE) |
82 | return handle_psl_slice_error(ctx, dsisr, irq_info->errstat); | 82 | return cxl_ops->handle_psl_slice_error(ctx, dsisr, |
83 | irq_info->errstat); | ||
83 | if (dsisr & CXL_PSL_DSISR_An_AE) { | 84 | if (dsisr & CXL_PSL_DSISR_An_AE) { |
84 | pr_devel("CXL interrupt: AFU Error 0x%016llx\n", irq_info->afu_err); | 85 | pr_devel("CXL interrupt: AFU Error 0x%016llx\n", irq_info->afu_err); |
85 | 86 | ||
@@ -103,7 +104,7 @@ irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info) | |||
103 | wake_up_all(&ctx->wq); | 104 | wake_up_all(&ctx->wq); |
104 | } | 105 | } |
105 | 106 | ||
106 | cxl_ack_irq(ctx, CXL_PSL_TFC_An_A, 0); | 107 | cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_A, 0); |
107 | return IRQ_HANDLED; | 108 | return IRQ_HANDLED; |
108 | } | 109 | } |
109 | if (dsisr & CXL_PSL_DSISR_An_OC) | 110 | if (dsisr & CXL_PSL_DSISR_An_OC) |
@@ -167,7 +168,8 @@ unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq, | |||
167 | return 0; | 168 | return 0; |
168 | } | 169 | } |
169 | 170 | ||
170 | cxl_setup_irq(adapter, hwirq, virq); | 171 | if (cxl_ops->setup_irq) |
172 | cxl_ops->setup_irq(adapter, hwirq, virq); | ||
171 | 173 | ||
172 | pr_devel("hwirq %#lx mapped to virq %u\n", hwirq, virq); | 174 | pr_devel("hwirq %#lx mapped to virq %u\n", hwirq, virq); |
173 | 175 | ||
@@ -195,7 +197,7 @@ int cxl_register_one_irq(struct cxl *adapter, | |||
195 | { | 197 | { |
196 | int hwirq, virq; | 198 | int hwirq, virq; |
197 | 199 | ||
198 | if ((hwirq = cxl_alloc_one_irq(adapter)) < 0) | 200 | if ((hwirq = cxl_ops->alloc_one_irq(adapter)) < 0) |
199 | return hwirq; | 201 | return hwirq; |
200 | 202 | ||
201 | if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie, name))) | 203 | if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie, name))) |
@@ -207,7 +209,7 @@ int cxl_register_one_irq(struct cxl *adapter, | |||
207 | return 0; | 209 | return 0; |
208 | 210 | ||
209 | err: | 211 | err: |
210 | cxl_release_one_irq(adapter, hwirq); | 212 | cxl_ops->release_one_irq(adapter, hwirq); |
211 | return -ENOMEM; | 213 | return -ENOMEM; |
212 | } | 214 | } |
213 | 215 | ||
@@ -230,7 +232,8 @@ int afu_allocate_irqs(struct cxl_context *ctx, u32 count) | |||
230 | /* Initialize the list head to hold irq names */ | 232 | /* Initialize the list head to hold irq names */ |
231 | INIT_LIST_HEAD(&ctx->irq_names); | 233 | INIT_LIST_HEAD(&ctx->irq_names); |
232 | 234 | ||
233 | if ((rc = cxl_alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, count))) | 235 | if ((rc = cxl_ops->alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, |
236 | count))) | ||
234 | return rc; | 237 | return rc; |
235 | 238 | ||
236 | /* Multiplexed PSL Interrupt */ | 239 | /* Multiplexed PSL Interrupt */ |
@@ -268,7 +271,7 @@ int afu_allocate_irqs(struct cxl_context *ctx, u32 count) | |||
268 | return 0; | 271 | return 0; |
269 | 272 | ||
270 | out: | 273 | out: |
271 | cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter); | 274 | cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter); |
272 | afu_irq_name_free(ctx); | 275 | afu_irq_name_free(ctx); |
273 | return -ENOMEM; | 276 | return -ENOMEM; |
274 | } | 277 | } |
@@ -319,7 +322,7 @@ void afu_release_irqs(struct cxl_context *ctx, void *cookie) | |||
319 | } | 322 | } |
320 | 323 | ||
321 | afu_irq_name_free(ctx); | 324 | afu_irq_name_free(ctx); |
322 | cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter); | 325 | cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter); |
323 | 326 | ||
324 | ctx->irq_count = 0; | 327 | ctx->irq_count = 0; |
325 | } | 328 | } |
diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c index 90933eb80fa3..a9051512198c 100644 --- a/drivers/misc/cxl/main.c +++ b/drivers/misc/cxl/main.c | |||
@@ -32,6 +32,8 @@ uint cxl_verbose; | |||
32 | module_param_named(verbose, cxl_verbose, uint, 0600); | 32 | module_param_named(verbose, cxl_verbose, uint, 0600); |
33 | MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); | 33 | MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); |
34 | 34 | ||
35 | const struct cxl_backend_ops *cxl_ops; | ||
36 | |||
35 | int cxl_afu_slbia(struct cxl_afu *afu) | 37 | int cxl_afu_slbia(struct cxl_afu *afu) |
36 | { | 38 | { |
37 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); | 39 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); |
@@ -46,7 +48,7 @@ int cxl_afu_slbia(struct cxl_afu *afu) | |||
46 | /* If the adapter has gone down, we can assume that we | 48 | /* If the adapter has gone down, we can assume that we |
47 | * will PERST it and that will invalidate everything. | 49 | * will PERST it and that will invalidate everything. |
48 | */ | 50 | */ |
49 | if (!cxl_adapter_link_ok(afu->adapter)) | 51 | if (!cxl_ops->link_ok(afu->adapter)) |
50 | return -EIO; | 52 | return -EIO; |
51 | cpu_relax(); | 53 | cpu_relax(); |
52 | } | 54 | } |
@@ -228,7 +230,7 @@ struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice) | |||
228 | 230 | ||
229 | afu->adapter = adapter; | 231 | afu->adapter = adapter; |
230 | afu->dev.parent = &adapter->dev; | 232 | afu->dev.parent = &adapter->dev; |
231 | afu->dev.release = cxl_release_afu; | 233 | afu->dev.release = cxl_ops->release_afu; |
232 | afu->slice = slice; | 234 | afu->slice = slice; |
233 | idr_init(&afu->contexts_idr); | 235 | idr_init(&afu->contexts_idr); |
234 | mutex_init(&afu->contexts_lock); | 236 | mutex_init(&afu->contexts_lock); |
@@ -244,10 +246,10 @@ struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice) | |||
244 | int cxl_afu_select_best_mode(struct cxl_afu *afu) | 246 | int cxl_afu_select_best_mode(struct cxl_afu *afu) |
245 | { | 247 | { |
246 | if (afu->modes_supported & CXL_MODE_DIRECTED) | 248 | if (afu->modes_supported & CXL_MODE_DIRECTED) |
247 | return cxl_afu_activate_mode(afu, CXL_MODE_DIRECTED); | 249 | return cxl_ops->afu_activate_mode(afu, CXL_MODE_DIRECTED); |
248 | 250 | ||
249 | if (afu->modes_supported & CXL_MODE_DEDICATED) | 251 | if (afu->modes_supported & CXL_MODE_DEDICATED) |
250 | return cxl_afu_activate_mode(afu, CXL_MODE_DEDICATED); | 252 | return cxl_ops->afu_activate_mode(afu, CXL_MODE_DEDICATED); |
251 | 253 | ||
252 | dev_warn(&afu->dev, "No supported programming modes available\n"); | 254 | dev_warn(&afu->dev, "No supported programming modes available\n"); |
253 | /* We don't fail this so the user can inspect sysfs */ | 255 | /* We don't fail this so the user can inspect sysfs */ |
@@ -269,6 +271,7 @@ static int __init init_cxl(void) | |||
269 | if ((rc = register_cxl_calls(&cxl_calls))) | 271 | if ((rc = register_cxl_calls(&cxl_calls))) |
270 | goto err; | 272 | goto err; |
271 | 273 | ||
274 | cxl_ops = &cxl_native_ops; | ||
272 | if ((rc = pci_register_driver(&cxl_pci_driver))) | 275 | if ((rc = pci_register_driver(&cxl_pci_driver))) |
273 | goto err1; | 276 | goto err1; |
274 | 277 | ||
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c index 3103e3327ea6..16d3b1a7d62c 100644 --- a/drivers/misc/cxl/native.c +++ b/drivers/misc/cxl/native.c | |||
@@ -42,7 +42,7 @@ static int afu_control(struct cxl_afu *afu, u64 command, | |||
42 | goto out; | 42 | goto out; |
43 | } | 43 | } |
44 | 44 | ||
45 | if (!cxl_adapter_link_ok(afu->adapter)) { | 45 | if (!cxl_ops->link_ok(afu->adapter)) { |
46 | afu->enabled = enabled; | 46 | afu->enabled = enabled; |
47 | rc = -EIO; | 47 | rc = -EIO; |
48 | goto out; | 48 | goto out; |
@@ -80,7 +80,7 @@ int cxl_afu_disable(struct cxl_afu *afu) | |||
80 | } | 80 | } |
81 | 81 | ||
82 | /* This will disable as well as reset */ | 82 | /* This will disable as well as reset */ |
83 | int __cxl_afu_reset(struct cxl_afu *afu) | 83 | static int __cxl_afu_reset(struct cxl_afu *afu) |
84 | { | 84 | { |
85 | pr_devel("AFU reset request\n"); | 85 | pr_devel("AFU reset request\n"); |
86 | 86 | ||
@@ -90,9 +90,9 @@ int __cxl_afu_reset(struct cxl_afu *afu) | |||
90 | false); | 90 | false); |
91 | } | 91 | } |
92 | 92 | ||
93 | int cxl_afu_check_and_enable(struct cxl_afu *afu) | 93 | static int cxl_afu_check_and_enable(struct cxl_afu *afu) |
94 | { | 94 | { |
95 | if (!cxl_adapter_link_ok(afu->adapter)) { | 95 | if (!cxl_ops->link_ok(afu->adapter)) { |
96 | WARN(1, "Refusing to enable afu while link down!\n"); | 96 | WARN(1, "Refusing to enable afu while link down!\n"); |
97 | return -EIO; | 97 | return -EIO; |
98 | } | 98 | } |
@@ -114,7 +114,7 @@ int cxl_psl_purge(struct cxl_afu *afu) | |||
114 | 114 | ||
115 | pr_devel("PSL purge request\n"); | 115 | pr_devel("PSL purge request\n"); |
116 | 116 | ||
117 | if (!cxl_adapter_link_ok(afu->adapter)) { | 117 | if (!cxl_ops->link_ok(afu->adapter)) { |
118 | dev_warn(&afu->dev, "PSL Purge called with link down, ignoring\n"); | 118 | dev_warn(&afu->dev, "PSL Purge called with link down, ignoring\n"); |
119 | rc = -EIO; | 119 | rc = -EIO; |
120 | goto out; | 120 | goto out; |
@@ -136,7 +136,7 @@ int cxl_psl_purge(struct cxl_afu *afu) | |||
136 | rc = -EBUSY; | 136 | rc = -EBUSY; |
137 | goto out; | 137 | goto out; |
138 | } | 138 | } |
139 | if (!cxl_adapter_link_ok(afu->adapter)) { | 139 | if (!cxl_ops->link_ok(afu->adapter)) { |
140 | rc = -EIO; | 140 | rc = -EIO; |
141 | goto out; | 141 | goto out; |
142 | } | 142 | } |
@@ -247,7 +247,7 @@ int cxl_tlb_slb_invalidate(struct cxl *adapter) | |||
247 | dev_warn(&adapter->dev, "WARNING: CXL adapter wide TLBIA timed out!\n"); | 247 | dev_warn(&adapter->dev, "WARNING: CXL adapter wide TLBIA timed out!\n"); |
248 | return -EBUSY; | 248 | return -EBUSY; |
249 | } | 249 | } |
250 | if (!cxl_adapter_link_ok(adapter)) | 250 | if (!cxl_ops->link_ok(adapter)) |
251 | return -EIO; | 251 | return -EIO; |
252 | cpu_relax(); | 252 | cpu_relax(); |
253 | } | 253 | } |
@@ -258,7 +258,7 @@ int cxl_tlb_slb_invalidate(struct cxl *adapter) | |||
258 | dev_warn(&adapter->dev, "WARNING: CXL adapter wide SLBIA timed out!\n"); | 258 | dev_warn(&adapter->dev, "WARNING: CXL adapter wide SLBIA timed out!\n"); |
259 | return -EBUSY; | 259 | return -EBUSY; |
260 | } | 260 | } |
261 | if (!cxl_adapter_link_ok(adapter)) | 261 | if (!cxl_ops->link_ok(adapter)) |
262 | return -EIO; | 262 | return -EIO; |
263 | cpu_relax(); | 263 | cpu_relax(); |
264 | } | 264 | } |
@@ -299,7 +299,7 @@ static void slb_invalid(struct cxl_context *ctx) | |||
299 | cxl_p1_write(adapter, CXL_PSL_SLBIA, CXL_TLB_SLB_IQ_LPIDPID); | 299 | cxl_p1_write(adapter, CXL_PSL_SLBIA, CXL_TLB_SLB_IQ_LPIDPID); |
300 | 300 | ||
301 | while (1) { | 301 | while (1) { |
302 | if (!cxl_adapter_link_ok(adapter)) | 302 | if (!cxl_ops->link_ok(adapter)) |
303 | break; | 303 | break; |
304 | slbia = cxl_p1_read(adapter, CXL_PSL_SLBIA); | 304 | slbia = cxl_p1_read(adapter, CXL_PSL_SLBIA); |
305 | if (!(slbia & CXL_TLB_SLB_P)) | 305 | if (!(slbia & CXL_TLB_SLB_P)) |
@@ -330,7 +330,7 @@ static int do_process_element_cmd(struct cxl_context *ctx, | |||
330 | rc = -EBUSY; | 330 | rc = -EBUSY; |
331 | goto out; | 331 | goto out; |
332 | } | 332 | } |
333 | if (!cxl_adapter_link_ok(ctx->afu->adapter)) { | 333 | if (!cxl_ops->link_ok(ctx->afu->adapter)) { |
334 | dev_warn(&ctx->afu->dev, "WARNING: Device link down, aborting Process Element Command!\n"); | 334 | dev_warn(&ctx->afu->dev, "WARNING: Device link down, aborting Process Element Command!\n"); |
335 | rc = -EIO; | 335 | rc = -EIO; |
336 | goto out; | 336 | goto out; |
@@ -386,7 +386,7 @@ static int terminate_process_element(struct cxl_context *ctx) | |||
386 | * should always succeed: it's not running if the hw has gone | 386 | * should always succeed: it's not running if the hw has gone |
387 | * away and is being reset. | 387 | * away and is being reset. |
388 | */ | 388 | */ |
389 | if (cxl_adapter_link_ok(ctx->afu->adapter)) | 389 | if (cxl_ops->link_ok(ctx->afu->adapter)) |
390 | rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_TERMINATE, | 390 | rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_TERMINATE, |
391 | CXL_PE_SOFTWARE_STATE_V | CXL_PE_SOFTWARE_STATE_T); | 391 | CXL_PE_SOFTWARE_STATE_V | CXL_PE_SOFTWARE_STATE_T); |
392 | ctx->elem->software_state = 0; /* Remove Valid bit */ | 392 | ctx->elem->software_state = 0; /* Remove Valid bit */ |
@@ -405,7 +405,7 @@ static int remove_process_element(struct cxl_context *ctx) | |||
405 | /* We could be asked to remove when the hw is down. Again, if | 405 | /* We could be asked to remove when the hw is down. Again, if |
406 | * the hw is down, the PE is gone, so we succeed. | 406 | * the hw is down, the PE is gone, so we succeed. |
407 | */ | 407 | */ |
408 | if (cxl_adapter_link_ok(ctx->afu->adapter)) | 408 | if (cxl_ops->link_ok(ctx->afu->adapter)) |
409 | rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_REMOVE, 0); | 409 | rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_REMOVE, 0); |
410 | 410 | ||
411 | if (!rc) | 411 | if (!rc) |
@@ -531,7 +531,7 @@ static int attach_afu_directed(struct cxl_context *ctx, u64 wed, u64 amr) | |||
531 | ctx->elem->common.wed = cpu_to_be64(wed); | 531 | ctx->elem->common.wed = cpu_to_be64(wed); |
532 | 532 | ||
533 | /* first guy needs to enable */ | 533 | /* first guy needs to enable */ |
534 | if ((result = cxl_afu_check_and_enable(ctx->afu))) | 534 | if ((result = cxl_ops->afu_check_and_enable(ctx->afu))) |
535 | return result; | 535 | return result; |
536 | 536 | ||
537 | return add_process_element(ctx); | 537 | return add_process_element(ctx); |
@@ -547,7 +547,7 @@ static int deactivate_afu_directed(struct cxl_afu *afu) | |||
547 | cxl_sysfs_afu_m_remove(afu); | 547 | cxl_sysfs_afu_m_remove(afu); |
548 | cxl_chardev_afu_remove(afu); | 548 | cxl_chardev_afu_remove(afu); |
549 | 549 | ||
550 | __cxl_afu_reset(afu); | 550 | cxl_ops->afu_reset(afu); |
551 | cxl_afu_disable(afu); | 551 | cxl_afu_disable(afu); |
552 | cxl_psl_purge(afu); | 552 | cxl_psl_purge(afu); |
553 | 553 | ||
@@ -611,7 +611,7 @@ static int attach_dedicated(struct cxl_context *ctx, u64 wed, u64 amr) | |||
611 | /* master only context for dedicated */ | 611 | /* master only context for dedicated */ |
612 | cxl_assign_psn_space(ctx); | 612 | cxl_assign_psn_space(ctx); |
613 | 613 | ||
614 | if ((rc = __cxl_afu_reset(afu))) | 614 | if ((rc = cxl_ops->afu_reset(afu))) |
615 | return rc; | 615 | return rc; |
616 | 616 | ||
617 | cxl_p2n_write(afu, CXL_PSL_WED_An, wed); | 617 | cxl_p2n_write(afu, CXL_PSL_WED_An, wed); |
@@ -631,7 +631,7 @@ static int deactivate_dedicated_process(struct cxl_afu *afu) | |||
631 | return 0; | 631 | return 0; |
632 | } | 632 | } |
633 | 633 | ||
634 | int _cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode) | 634 | static int cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode) |
635 | { | 635 | { |
636 | if (mode == CXL_MODE_DIRECTED) | 636 | if (mode == CXL_MODE_DIRECTED) |
637 | return deactivate_afu_directed(afu); | 637 | return deactivate_afu_directed(afu); |
@@ -640,19 +640,14 @@ int _cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode) | |||
640 | return 0; | 640 | return 0; |
641 | } | 641 | } |
642 | 642 | ||
643 | int cxl_afu_deactivate_mode(struct cxl_afu *afu) | 643 | static int cxl_afu_activate_mode(struct cxl_afu *afu, int mode) |
644 | { | ||
645 | return _cxl_afu_deactivate_mode(afu, afu->current_mode); | ||
646 | } | ||
647 | |||
648 | int cxl_afu_activate_mode(struct cxl_afu *afu, int mode) | ||
649 | { | 644 | { |
650 | if (!mode) | 645 | if (!mode) |
651 | return 0; | 646 | return 0; |
652 | if (!(mode & afu->modes_supported)) | 647 | if (!(mode & afu->modes_supported)) |
653 | return -EINVAL; | 648 | return -EINVAL; |
654 | 649 | ||
655 | if (!cxl_adapter_link_ok(afu->adapter)) { | 650 | if (!cxl_ops->link_ok(afu->adapter)) { |
656 | WARN(1, "Device link is down, refusing to activate!\n"); | 651 | WARN(1, "Device link is down, refusing to activate!\n"); |
657 | return -EIO; | 652 | return -EIO; |
658 | } | 653 | } |
@@ -665,9 +660,9 @@ int cxl_afu_activate_mode(struct cxl_afu *afu, int mode) | |||
665 | return -EINVAL; | 660 | return -EINVAL; |
666 | } | 661 | } |
667 | 662 | ||
668 | int cxl_attach_process(struct cxl_context *ctx, bool kernel, u64 wed, u64 amr) | 663 | static int cxl_attach_process(struct cxl_context *ctx, bool kernel, u64 wed, u64 amr) |
669 | { | 664 | { |
670 | if (!cxl_adapter_link_ok(ctx->afu->adapter)) { | 665 | if (!cxl_ops->link_ok(ctx->afu->adapter)) { |
671 | WARN(1, "Device link is down, refusing to attach process!\n"); | 666 | WARN(1, "Device link is down, refusing to attach process!\n"); |
672 | return -EIO; | 667 | return -EIO; |
673 | } | 668 | } |
@@ -684,7 +679,7 @@ int cxl_attach_process(struct cxl_context *ctx, bool kernel, u64 wed, u64 amr) | |||
684 | 679 | ||
685 | static inline int detach_process_native_dedicated(struct cxl_context *ctx) | 680 | static inline int detach_process_native_dedicated(struct cxl_context *ctx) |
686 | { | 681 | { |
687 | __cxl_afu_reset(ctx->afu); | 682 | cxl_ops->afu_reset(ctx->afu); |
688 | cxl_afu_disable(ctx->afu); | 683 | cxl_afu_disable(ctx->afu); |
689 | cxl_psl_purge(ctx->afu); | 684 | cxl_psl_purge(ctx->afu); |
690 | return 0; | 685 | return 0; |
@@ -702,7 +697,7 @@ static inline int detach_process_native_afu_directed(struct cxl_context *ctx) | |||
702 | return 0; | 697 | return 0; |
703 | } | 698 | } |
704 | 699 | ||
705 | int cxl_detach_process(struct cxl_context *ctx) | 700 | static int cxl_detach_process(struct cxl_context *ctx) |
706 | { | 701 | { |
707 | trace_cxl_detach(ctx); | 702 | trace_cxl_detach(ctx); |
708 | 703 | ||
@@ -719,7 +714,7 @@ static int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info) | |||
719 | /* If the adapter has gone away, we can't get any meaningful | 714 | /* If the adapter has gone away, we can't get any meaningful |
720 | * information. | 715 | * information. |
721 | */ | 716 | */ |
722 | if (!cxl_adapter_link_ok(afu->adapter)) | 717 | if (!cxl_ops->link_ok(afu->adapter)) |
723 | return -EIO; | 718 | return -EIO; |
724 | 719 | ||
725 | info->dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); | 720 | info->dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); |
@@ -734,7 +729,7 @@ static int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info) | |||
734 | return 0; | 729 | return 0; |
735 | } | 730 | } |
736 | 731 | ||
737 | irqreturn_t handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, u64 errstat) | 732 | static irqreturn_t handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, u64 errstat) |
738 | { | 733 | { |
739 | u64 fir1, fir2, fir_slice, serr, afu_debug; | 734 | u64 fir1, fir2, fir_slice, serr, afu_debug; |
740 | 735 | ||
@@ -754,7 +749,7 @@ irqreturn_t handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, u64 errst | |||
754 | dev_crit(&ctx->afu->dev, "STOPPING CXL TRACE\n"); | 749 | dev_crit(&ctx->afu->dev, "STOPPING CXL TRACE\n"); |
755 | cxl_stop_trace(ctx->afu->adapter); | 750 | cxl_stop_trace(ctx->afu->adapter); |
756 | 751 | ||
757 | return cxl_ack_irq(ctx, 0, errstat); | 752 | return cxl_ops->ack_irq(ctx, 0, errstat); |
758 | } | 753 | } |
759 | 754 | ||
760 | static irqreturn_t fail_psl_irq(struct cxl_afu *afu, struct cxl_irq_info *irq_info) | 755 | static irqreturn_t fail_psl_irq(struct cxl_afu *afu, struct cxl_irq_info *irq_info) |
@@ -868,7 +863,7 @@ void cxl_release_psl_err_irq(struct cxl *adapter) | |||
868 | 863 | ||
869 | cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000); | 864 | cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000); |
870 | cxl_unmap_irq(adapter->err_virq, adapter); | 865 | cxl_unmap_irq(adapter->err_virq, adapter); |
871 | cxl_release_one_irq(adapter, adapter->err_hwirq); | 866 | cxl_ops->release_one_irq(adapter, adapter->err_hwirq); |
872 | kfree(adapter->irq_name); | 867 | kfree(adapter->irq_name); |
873 | } | 868 | } |
874 | 869 | ||
@@ -904,7 +899,7 @@ void cxl_release_serr_irq(struct cxl_afu *afu) | |||
904 | 899 | ||
905 | cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000); | 900 | cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000); |
906 | cxl_unmap_irq(afu->serr_virq, afu); | 901 | cxl_unmap_irq(afu->serr_virq, afu); |
907 | cxl_release_one_irq(afu->adapter, afu->serr_hwirq); | 902 | cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq); |
908 | kfree(afu->err_irq_name); | 903 | kfree(afu->err_irq_name); |
909 | } | 904 | } |
910 | 905 | ||
@@ -932,7 +927,7 @@ void cxl_release_psl_irq(struct cxl_afu *afu) | |||
932 | return; | 927 | return; |
933 | 928 | ||
934 | cxl_unmap_irq(afu->psl_virq, afu); | 929 | cxl_unmap_irq(afu->psl_virq, afu); |
935 | cxl_release_one_irq(afu->adapter, afu->psl_hwirq); | 930 | cxl_ops->release_one_irq(afu->adapter, afu->psl_hwirq); |
936 | kfree(afu->psl_irq_name); | 931 | kfree(afu->psl_irq_name); |
937 | } | 932 | } |
938 | 933 | ||
@@ -950,7 +945,7 @@ static void recover_psl_err(struct cxl_afu *afu, u64 errstat) | |||
950 | cxl_p2n_write(afu, CXL_PSL_ErrStat_An, errstat); | 945 | cxl_p2n_write(afu, CXL_PSL_ErrStat_An, errstat); |
951 | } | 946 | } |
952 | 947 | ||
953 | int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask) | 948 | static int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask) |
954 | { | 949 | { |
955 | trace_cxl_psl_irq_ack(ctx, tfc); | 950 | trace_cxl_psl_irq_ack(ctx, tfc); |
956 | if (tfc) | 951 | if (tfc) |
@@ -966,38 +961,74 @@ int cxl_check_error(struct cxl_afu *afu) | |||
966 | return (cxl_p1n_read(afu, CXL_PSL_SCNTL_An) == ~0ULL); | 961 | return (cxl_p1n_read(afu, CXL_PSL_SCNTL_An) == ~0ULL); |
967 | } | 962 | } |
968 | 963 | ||
969 | u64 cxl_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off) | 964 | static int cxl_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off, u64 *out) |
970 | { | 965 | { |
971 | if (likely(cxl_adapter_link_ok(afu->adapter))) | 966 | if (unlikely(!cxl_ops->link_ok(afu->adapter))) |
972 | return in_le64((afu)->afu_desc_mmio + (afu)->crs_offset + | 967 | return -EIO; |
973 | ((cr) * (afu)->crs_len) + (off)); | 968 | if (unlikely(off >= afu->crs_len)) |
974 | else | 969 | return -ERANGE; |
975 | return ~0ULL; | 970 | *out = in_le64(afu->afu_desc_mmio + afu->crs_offset + |
971 | (cr * afu->crs_len) + off); | ||
972 | return 0; | ||
976 | } | 973 | } |
977 | 974 | ||
978 | u32 cxl_afu_cr_read32(struct cxl_afu *afu, int cr, u64 off) | 975 | static int cxl_afu_cr_read32(struct cxl_afu *afu, int cr, u64 off, u32 *out) |
979 | { | 976 | { |
980 | if (likely(cxl_adapter_link_ok(afu->adapter))) | 977 | if (unlikely(!cxl_ops->link_ok(afu->adapter))) |
981 | return in_le32((afu)->afu_desc_mmio + (afu)->crs_offset + | 978 | return -EIO; |
982 | ((cr) * (afu)->crs_len) + (off)); | 979 | if (unlikely(off >= afu->crs_len)) |
983 | else | 980 | return -ERANGE; |
984 | return 0xffffffff; | 981 | *out = in_le32(afu->afu_desc_mmio + afu->crs_offset + |
982 | (cr * afu->crs_len) + off); | ||
983 | return 0; | ||
985 | } | 984 | } |
986 | 985 | ||
987 | u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off) | 986 | static int cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off, u16 *out) |
988 | { | 987 | { |
989 | u64 aligned_off = off & ~0x3L; | 988 | u64 aligned_off = off & ~0x3L; |
990 | u32 val; | 989 | u32 val; |
990 | int rc; | ||
991 | 991 | ||
992 | val = cxl_afu_cr_read32(afu, cr, aligned_off); | 992 | rc = cxl_afu_cr_read32(afu, cr, aligned_off, &val); |
993 | return (val >> ((off & 0x2) * 8)) & 0xffff; | 993 | if (!rc) |
994 | *out = (val >> ((off & 0x3) * 8)) & 0xffff; | ||
995 | return rc; | ||
994 | } | 996 | } |
995 | 997 | ||
996 | u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off) | 998 | static int cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off, u8 *out) |
997 | { | 999 | { |
998 | u64 aligned_off = off & ~0x3L; | 1000 | u64 aligned_off = off & ~0x3L; |
999 | u32 val; | 1001 | u32 val; |
1002 | int rc; | ||
1000 | 1003 | ||
1001 | val = cxl_afu_cr_read32(afu, cr, aligned_off); | 1004 | rc = cxl_afu_cr_read32(afu, cr, aligned_off, &val); |
1002 | return (val >> ((off & 0x3) * 8)) & 0xff; | 1005 | if (!rc) |
1006 | *out = (val >> ((off & 0x3) * 8)) & 0xff; | ||
1007 | return rc; | ||
1003 | } | 1008 | } |
1009 | |||
1010 | const struct cxl_backend_ops cxl_native_ops = { | ||
1011 | .module = THIS_MODULE, | ||
1012 | .adapter_reset = cxl_reset, | ||
1013 | .alloc_one_irq = cxl_alloc_one_irq, | ||
1014 | .release_one_irq = cxl_release_one_irq, | ||
1015 | .alloc_irq_ranges = cxl_alloc_irq_ranges, | ||
1016 | .release_irq_ranges = cxl_release_irq_ranges, | ||
1017 | .setup_irq = cxl_setup_irq, | ||
1018 | .handle_psl_slice_error = handle_psl_slice_error, | ||
1019 | .psl_interrupt = NULL, | ||
1020 | .ack_irq = cxl_ack_irq, | ||
1021 | .attach_process = cxl_attach_process, | ||
1022 | .detach_process = cxl_detach_process, | ||
1023 | .link_ok = cxl_adapter_link_ok, | ||
1024 | .release_afu = cxl_release_afu, | ||
1025 | .afu_read_err_buffer = cxl_afu_read_err_buffer, | ||
1026 | .afu_check_and_enable = cxl_afu_check_and_enable, | ||
1027 | .afu_activate_mode = cxl_afu_activate_mode, | ||
1028 | .afu_deactivate_mode = cxl_afu_deactivate_mode, | ||
1029 | .afu_reset = __cxl_afu_reset, | ||
1030 | .afu_cr_read8 = cxl_afu_cr_read8, | ||
1031 | .afu_cr_read16 = cxl_afu_cr_read16, | ||
1032 | .afu_cr_read32 = cxl_afu_cr_read32, | ||
1033 | .afu_cr_read64 = cxl_afu_cr_read64, | ||
1034 | }; | ||
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index c6279e5068b2..6e2c2748dd4f 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c | |||
@@ -646,7 +646,8 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu) | |||
646 | 646 | ||
647 | static int cxl_afu_descriptor_looks_ok(struct cxl_afu *afu) | 647 | static int cxl_afu_descriptor_looks_ok(struct cxl_afu *afu) |
648 | { | 648 | { |
649 | int i; | 649 | int i, rc; |
650 | u32 val; | ||
650 | 651 | ||
651 | if (afu->psa && afu->adapter->ps_size < | 652 | if (afu->psa && afu->adapter->ps_size < |
652 | (afu->pp_offset + afu->pp_size*afu->max_procs_virtualised)) { | 653 | (afu->pp_offset + afu->pp_size*afu->max_procs_virtualised)) { |
@@ -658,7 +659,8 @@ static int cxl_afu_descriptor_looks_ok(struct cxl_afu *afu) | |||
658 | dev_warn(&afu->dev, "AFU uses < PAGE_SIZE per-process PSA!"); | 659 | dev_warn(&afu->dev, "AFU uses < PAGE_SIZE per-process PSA!"); |
659 | 660 | ||
660 | for (i = 0; i < afu->crs_num; i++) { | 661 | for (i = 0; i < afu->crs_num; i++) { |
661 | if ((cxl_afu_cr_read32(afu, i, 0) == 0)) { | 662 | rc = cxl_ops->afu_cr_read32(afu, i, 0, &val); |
663 | if (rc || val == 0) { | ||
662 | dev_err(&afu->dev, "ABORTING: AFU configuration record %i is invalid\n", i); | 664 | dev_err(&afu->dev, "ABORTING: AFU configuration record %i is invalid\n", i); |
663 | return -EINVAL; | 665 | return -EINVAL; |
664 | } | 666 | } |
@@ -679,7 +681,7 @@ static int sanitise_afu_regs(struct cxl_afu *afu) | |||
679 | reg = cxl_p2n_read(afu, CXL_AFU_Cntl_An); | 681 | reg = cxl_p2n_read(afu, CXL_AFU_Cntl_An); |
680 | if ((reg & CXL_AFU_Cntl_An_ES_MASK) != CXL_AFU_Cntl_An_ES_Disabled) { | 682 | if ((reg & CXL_AFU_Cntl_An_ES_MASK) != CXL_AFU_Cntl_An_ES_Disabled) { |
681 | dev_warn(&afu->dev, "WARNING: AFU was not disabled: %#016llx\n", reg); | 683 | dev_warn(&afu->dev, "WARNING: AFU was not disabled: %#016llx\n", reg); |
682 | if (__cxl_afu_reset(afu)) | 684 | if (cxl_ops->afu_reset(afu)) |
683 | return -EIO; | 685 | return -EIO; |
684 | if (cxl_afu_disable(afu)) | 686 | if (cxl_afu_disable(afu)) |
685 | return -EIO; | 687 | return -EIO; |
@@ -775,7 +777,7 @@ static int cxl_configure_afu(struct cxl_afu *afu, struct cxl *adapter, struct pc | |||
775 | goto err1; | 777 | goto err1; |
776 | 778 | ||
777 | /* We need to reset the AFU before we can read the AFU descriptor */ | 779 | /* We need to reset the AFU before we can read the AFU descriptor */ |
778 | if ((rc = __cxl_afu_reset(afu))) | 780 | if ((rc = cxl_ops->afu_reset(afu))) |
779 | goto err1; | 781 | goto err1; |
780 | 782 | ||
781 | if (cxl_verbose) | 783 | if (cxl_verbose) |
@@ -876,7 +878,7 @@ static void cxl_remove_afu(struct cxl_afu *afu) | |||
876 | spin_unlock(&afu->adapter->afu_list_lock); | 878 | spin_unlock(&afu->adapter->afu_list_lock); |
877 | 879 | ||
878 | cxl_context_detach_all(afu); | 880 | cxl_context_detach_all(afu); |
879 | cxl_afu_deactivate_mode(afu); | 881 | cxl_ops->afu_deactivate_mode(afu, afu->current_mode); |
880 | 882 | ||
881 | cxl_deconfigure_afu(afu); | 883 | cxl_deconfigure_afu(afu); |
882 | device_unregister(&afu->dev); | 884 | device_unregister(&afu->dev); |
@@ -1398,7 +1400,7 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev, | |||
1398 | return result; | 1400 | return result; |
1399 | 1401 | ||
1400 | cxl_context_detach_all(afu); | 1402 | cxl_context_detach_all(afu); |
1401 | cxl_afu_deactivate_mode(afu); | 1403 | cxl_ops->afu_deactivate_mode(afu, afu->current_mode); |
1402 | cxl_deconfigure_afu(afu); | 1404 | cxl_deconfigure_afu(afu); |
1403 | } | 1405 | } |
1404 | cxl_deconfigure_adapter(adapter); | 1406 | cxl_deconfigure_adapter(adapter); |
@@ -1445,7 +1447,7 @@ static pci_ers_result_t cxl_pci_slot_reset(struct pci_dev *pdev) | |||
1445 | 1447 | ||
1446 | afu_dev->dev.archdata.cxl_ctx = ctx; | 1448 | afu_dev->dev.archdata.cxl_ctx = ctx; |
1447 | 1449 | ||
1448 | if (cxl_afu_check_and_enable(afu)) | 1450 | if (cxl_ops->afu_check_and_enable(afu)) |
1449 | goto err; | 1451 | goto err; |
1450 | 1452 | ||
1451 | afu_dev->error_state = pci_channel_io_normal; | 1453 | afu_dev->error_state = pci_channel_io_normal; |
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index 02006f7109a8..300eafe4ed43 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c | |||
@@ -69,7 +69,7 @@ static ssize_t reset_adapter_store(struct device *device, | |||
69 | if ((rc != 1) || (val != 1)) | 69 | if ((rc != 1) || (val != 1)) |
70 | return -EINVAL; | 70 | return -EINVAL; |
71 | 71 | ||
72 | if ((rc = cxl_reset(adapter))) | 72 | if ((rc = cxl_ops->adapter_reset(adapter))) |
73 | return rc; | 73 | return rc; |
74 | return count; | 74 | return count; |
75 | } | 75 | } |
@@ -211,7 +211,7 @@ static ssize_t reset_store_afu(struct device *device, | |||
211 | goto err; | 211 | goto err; |
212 | } | 212 | } |
213 | 213 | ||
214 | if ((rc = __cxl_afu_reset(afu))) | 214 | if ((rc = cxl_ops->afu_reset(afu))) |
215 | goto err; | 215 | goto err; |
216 | 216 | ||
217 | rc = count; | 217 | rc = count; |
@@ -348,7 +348,7 @@ static ssize_t mode_store(struct device *device, struct device_attribute *attr, | |||
348 | } | 348 | } |
349 | 349 | ||
350 | /* | 350 | /* |
351 | * cxl_afu_deactivate_mode needs to be done outside the lock, prevent | 351 | * afu_deactivate_mode needs to be done outside the lock, prevent |
352 | * other contexts coming in before we are ready: | 352 | * other contexts coming in before we are ready: |
353 | */ | 353 | */ |
354 | old_mode = afu->current_mode; | 354 | old_mode = afu->current_mode; |
@@ -357,9 +357,9 @@ static ssize_t mode_store(struct device *device, struct device_attribute *attr, | |||
357 | 357 | ||
358 | mutex_unlock(&afu->contexts_lock); | 358 | mutex_unlock(&afu->contexts_lock); |
359 | 359 | ||
360 | if ((rc = _cxl_afu_deactivate_mode(afu, old_mode))) | 360 | if ((rc = cxl_ops->afu_deactivate_mode(afu, old_mode))) |
361 | return rc; | 361 | return rc; |
362 | if ((rc = cxl_afu_activate_mode(afu, mode))) | 362 | if ((rc = cxl_ops->afu_activate_mode(afu, mode))) |
363 | return rc; | 363 | return rc; |
364 | 364 | ||
365 | return count; | 365 | return count; |
@@ -389,7 +389,7 @@ static ssize_t afu_eb_read(struct file *filp, struct kobject *kobj, | |||
389 | struct cxl_afu *afu = to_cxl_afu(container_of(kobj, | 389 | struct cxl_afu *afu = to_cxl_afu(container_of(kobj, |
390 | struct device, kobj)); | 390 | struct device, kobj)); |
391 | 391 | ||
392 | return cxl_afu_read_err_buffer(afu, buf, off, count); | 392 | return cxl_ops->afu_read_err_buffer(afu, buf, off, count); |
393 | } | 393 | } |
394 | 394 | ||
395 | static struct device_attribute afu_attrs[] = { | 395 | static struct device_attribute afu_attrs[] = { |
@@ -469,10 +469,12 @@ static ssize_t afu_read_config(struct file *filp, struct kobject *kobj, | |||
469 | struct afu_config_record *cr = to_cr(kobj); | 469 | struct afu_config_record *cr = to_cr(kobj); |
470 | struct cxl_afu *afu = to_cxl_afu(container_of(kobj->parent, struct device, kobj)); | 470 | struct cxl_afu *afu = to_cxl_afu(container_of(kobj->parent, struct device, kobj)); |
471 | 471 | ||
472 | u64 i, j, val; | 472 | u64 i, j, val, rc; |
473 | 473 | ||
474 | for (i = 0; i < count;) { | 474 | for (i = 0; i < count;) { |
475 | val = cxl_afu_cr_read64(afu, cr->cr, off & ~0x7); | 475 | rc = cxl_ops->afu_cr_read64(afu, cr->cr, off & ~0x7, &val); |
476 | if (rc) | ||
477 | val = ~0ULL; | ||
476 | for (j = off & 0x7; j < 8 && i < count; i++, j++, off++) | 478 | for (j = off & 0x7; j < 8 && i < count; i++, j++, off++) |
477 | buf[i] = (val >> (j * 8)) & 0xff; | 479 | buf[i] = (val >> (j * 8)) & 0xff; |
478 | } | 480 | } |
@@ -517,9 +519,17 @@ static struct afu_config_record *cxl_sysfs_afu_new_cr(struct cxl_afu *afu, int c | |||
517 | return ERR_PTR(-ENOMEM); | 519 | return ERR_PTR(-ENOMEM); |
518 | 520 | ||
519 | cr->cr = cr_idx; | 521 | cr->cr = cr_idx; |
520 | cr->device = cxl_afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID); | 522 | |
521 | cr->vendor = cxl_afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID); | 523 | rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID, &cr->device); |
522 | cr->class = cxl_afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION) >> 8; | 524 | if (rc) |
525 | goto err; | ||
526 | rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID, &cr->vendor); | ||
527 | if (rc) | ||
528 | goto err; | ||
529 | rc = cxl_ops->afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION, &cr->class); | ||
530 | if (rc) | ||
531 | goto err; | ||
532 | cr->class >>= 8; | ||
523 | 533 | ||
524 | /* | 534 | /* |
525 | * Export raw AFU PCIe like config record. For now this is read only by | 535 | * Export raw AFU PCIe like config record. For now this is read only by |
diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c index cbd4331fb45c..e8a8eed6f006 100644 --- a/drivers/misc/cxl/vphb.c +++ b/drivers/misc/cxl/vphb.c | |||
@@ -49,7 +49,7 @@ static bool cxl_pci_enable_device_hook(struct pci_dev *dev) | |||
49 | phb = pci_bus_to_host(dev->bus); | 49 | phb = pci_bus_to_host(dev->bus); |
50 | afu = (struct cxl_afu *)phb->private_data; | 50 | afu = (struct cxl_afu *)phb->private_data; |
51 | 51 | ||
52 | if (!cxl_adapter_link_ok(afu->adapter)) { | 52 | if (!cxl_ops->link_ok(afu->adapter)) { |
53 | dev_warn(&dev->dev, "%s: Device link is down, refusing to enable AFU\n", __func__); | 53 | dev_warn(&dev->dev, "%s: Device link is down, refusing to enable AFU\n", __func__); |
54 | return false; | 54 | return false; |
55 | } | 55 | } |
@@ -66,7 +66,7 @@ static bool cxl_pci_enable_device_hook(struct pci_dev *dev) | |||
66 | return false; | 66 | return false; |
67 | dev->dev.archdata.cxl_ctx = ctx; | 67 | dev->dev.archdata.cxl_ctx = ctx; |
68 | 68 | ||
69 | return (cxl_afu_check_and_enable(afu) == 0); | 69 | return (cxl_ops->afu_check_and_enable(afu) == 0); |
70 | } | 70 | } |
71 | 71 | ||
72 | static void cxl_pci_disable_device(struct pci_dev *dev) | 72 | static void cxl_pci_disable_device(struct pci_dev *dev) |
@@ -161,7 +161,7 @@ static inline bool cxl_config_link_ok(struct pci_bus *bus) | |||
161 | if (phb == NULL) | 161 | if (phb == NULL) |
162 | return false; | 162 | return false; |
163 | afu = (struct cxl_afu *)phb->private_data; | 163 | afu = (struct cxl_afu *)phb->private_data; |
164 | return cxl_adapter_link_ok(afu->adapter); | 164 | return cxl_ops->link_ok(afu->adapter); |
165 | } | 165 | } |
166 | 166 | ||
167 | static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn, | 167 | static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn, |