diff options
author | Christophe Lombard <clombard@linux.vnet.ibm.com> | 2016-03-04 06:26:41 -0500 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2016-03-09 07:40:00 -0500 |
commit | 0d400f77c19e8d2606f8194846bcf18ebdc9df2a (patch) | |
tree | 307436d00d93f55e2aa27d2233c91346c14e8961 | |
parent | d601ea918b878582e60b773f2f943d8d292b2abf (diff) |
cxl: Adapter failure handling
Check the AFU state whenever an API is called. The hypervisor may
issue a reset of the adapter when it detects a fault. When it happens,
it launches an error recovery which will either move the AFU to a
permanent failure state, or in the disabled state.
If the AFU is found to be disabled, detach all existing contexts from
it before issuing a AFU reset to re-enable it.
Before detaching contexts, notify any kernel driver through the EEH
callbacks of the AFU pci device.
Co-authored-by: Frederic Barrat <fbarrat@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/context.c | 2 | ||||
-rw-r--r-- | drivers/misc/cxl/cxl.h | 18 | ||||
-rw-r--r-- | drivers/misc/cxl/file.c | 10 | ||||
-rw-r--r-- | drivers/misc/cxl/guest.c | 167 | ||||
-rw-r--r-- | drivers/misc/cxl/main.c | 2 | ||||
-rw-r--r-- | drivers/misc/cxl/native.c | 32 | ||||
-rw-r--r-- | drivers/misc/cxl/vphb.c | 2 |
7 files changed, 198 insertions, 35 deletions
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c index 180c85a32825..10370f280500 100644 --- a/drivers/misc/cxl/context.c +++ b/drivers/misc/cxl/context.c | |||
@@ -220,7 +220,7 @@ int __detach_context(struct cxl_context *ctx) | |||
220 | * If detach fails when hw is down, we don't care. | 220 | * If detach fails when hw is down, we don't care. |
221 | */ | 221 | */ |
222 | WARN_ON(cxl_ops->detach_process(ctx) && | 222 | WARN_ON(cxl_ops->detach_process(ctx) && |
223 | cxl_ops->link_ok(ctx->afu->adapter)); | 223 | cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)); |
224 | flush_work(&ctx->fault_work); /* Only needed for dedicated process */ | 224 | flush_work(&ctx->fault_work); /* Only needed for dedicated process */ |
225 | 225 | ||
226 | /* release the reference to the group leader and mm handling pid */ | 226 | /* 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 b388c971810f..e345860c25eb 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h | |||
@@ -379,6 +379,8 @@ struct cxl_afu_guest { | |||
379 | phys_addr_t p2n_phys; | 379 | phys_addr_t p2n_phys; |
380 | u64 p2n_size; | 380 | u64 p2n_size; |
381 | int max_ints; | 381 | int max_ints; |
382 | struct mutex recovery_lock; | ||
383 | int previous_state; | ||
382 | }; | 384 | }; |
383 | 385 | ||
384 | struct cxl_afu { | 386 | struct cxl_afu { |
@@ -617,7 +619,7 @@ struct cxl_process_element { | |||
617 | __be32 software_state; | 619 | __be32 software_state; |
618 | } __packed; | 620 | } __packed; |
619 | 621 | ||
620 | static inline bool cxl_adapter_link_ok(struct cxl *cxl) | 622 | static inline bool cxl_adapter_link_ok(struct cxl *cxl, struct cxl_afu *afu) |
621 | { | 623 | { |
622 | struct pci_dev *pdev; | 624 | struct pci_dev *pdev; |
623 | 625 | ||
@@ -636,13 +638,13 @@ static inline void __iomem *_cxl_p1_addr(struct cxl *cxl, cxl_p1_reg_t reg) | |||
636 | 638 | ||
637 | static inline void cxl_p1_write(struct cxl *cxl, cxl_p1_reg_t reg, u64 val) | 639 | static inline void cxl_p1_write(struct cxl *cxl, cxl_p1_reg_t reg, u64 val) |
638 | { | 640 | { |
639 | if (likely(cxl_adapter_link_ok(cxl))) | 641 | if (likely(cxl_adapter_link_ok(cxl, NULL))) |
640 | out_be64(_cxl_p1_addr(cxl, reg), val); | 642 | out_be64(_cxl_p1_addr(cxl, reg), val); |
641 | } | 643 | } |
642 | 644 | ||
643 | static inline u64 cxl_p1_read(struct cxl *cxl, cxl_p1_reg_t reg) | 645 | static inline u64 cxl_p1_read(struct cxl *cxl, cxl_p1_reg_t reg) |
644 | { | 646 | { |
645 | if (likely(cxl_adapter_link_ok(cxl))) | 647 | if (likely(cxl_adapter_link_ok(cxl, NULL))) |
646 | return in_be64(_cxl_p1_addr(cxl, reg)); | 648 | return in_be64(_cxl_p1_addr(cxl, reg)); |
647 | else | 649 | else |
648 | return ~0ULL; | 650 | return ~0ULL; |
@@ -656,13 +658,13 @@ static inline void __iomem *_cxl_p1n_addr(struct cxl_afu *afu, cxl_p1n_reg_t reg | |||
656 | 658 | ||
657 | static inline void cxl_p1n_write(struct cxl_afu *afu, cxl_p1n_reg_t reg, u64 val) | 659 | static inline void cxl_p1n_write(struct cxl_afu *afu, cxl_p1n_reg_t reg, u64 val) |
658 | { | 660 | { |
659 | if (likely(cxl_adapter_link_ok(afu->adapter))) | 661 | if (likely(cxl_adapter_link_ok(afu->adapter, afu))) |
660 | out_be64(_cxl_p1n_addr(afu, reg), val); | 662 | out_be64(_cxl_p1n_addr(afu, reg), val); |
661 | } | 663 | } |
662 | 664 | ||
663 | static inline u64 cxl_p1n_read(struct cxl_afu *afu, cxl_p1n_reg_t reg) | 665 | static inline u64 cxl_p1n_read(struct cxl_afu *afu, cxl_p1n_reg_t reg) |
664 | { | 666 | { |
665 | if (likely(cxl_adapter_link_ok(afu->adapter))) | 667 | if (likely(cxl_adapter_link_ok(afu->adapter, afu))) |
666 | return in_be64(_cxl_p1n_addr(afu, reg)); | 668 | return in_be64(_cxl_p1n_addr(afu, reg)); |
667 | else | 669 | else |
668 | return ~0ULL; | 670 | return ~0ULL; |
@@ -675,13 +677,13 @@ static inline void __iomem *_cxl_p2n_addr(struct cxl_afu *afu, cxl_p2n_reg_t reg | |||
675 | 677 | ||
676 | static inline void cxl_p2n_write(struct cxl_afu *afu, cxl_p2n_reg_t reg, u64 val) | 678 | static inline void cxl_p2n_write(struct cxl_afu *afu, cxl_p2n_reg_t reg, u64 val) |
677 | { | 679 | { |
678 | if (likely(cxl_adapter_link_ok(afu->adapter))) | 680 | if (likely(cxl_adapter_link_ok(afu->adapter, afu))) |
679 | out_be64(_cxl_p2n_addr(afu, reg), val); | 681 | out_be64(_cxl_p2n_addr(afu, reg), val); |
680 | } | 682 | } |
681 | 683 | ||
682 | static inline u64 cxl_p2n_read(struct cxl_afu *afu, cxl_p2n_reg_t reg) | 684 | static inline u64 cxl_p2n_read(struct cxl_afu *afu, cxl_p2n_reg_t reg) |
683 | { | 685 | { |
684 | if (likely(cxl_adapter_link_ok(afu->adapter))) | 686 | if (likely(cxl_adapter_link_ok(afu->adapter, afu))) |
685 | return in_be64(_cxl_p2n_addr(afu, reg)); | 687 | return in_be64(_cxl_p2n_addr(afu, reg)); |
686 | else | 688 | else |
687 | return ~0ULL; | 689 | return ~0ULL; |
@@ -857,7 +859,7 @@ struct cxl_backend_ops { | |||
857 | u64 wed, u64 amr); | 859 | u64 wed, u64 amr); |
858 | int (*detach_process)(struct cxl_context *ctx); | 860 | int (*detach_process)(struct cxl_context *ctx); |
859 | bool (*support_attributes)(const char *attr_name, enum cxl_attrs type); | 861 | bool (*support_attributes)(const char *attr_name, enum cxl_attrs type); |
860 | bool (*link_ok)(struct cxl *cxl); | 862 | bool (*link_ok)(struct cxl *cxl, struct cxl_afu *afu); |
861 | void (*release_afu)(struct device *dev); | 863 | void (*release_afu)(struct device *dev); |
862 | ssize_t (*afu_read_err_buffer)(struct cxl_afu *afu, char *buf, | 864 | ssize_t (*afu_read_err_buffer)(struct cxl_afu *afu, char *buf, |
863 | loff_t off, size_t count); | 865 | loff_t off, size_t count); |
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c index e16046292dd6..eec468f1612f 100644 --- a/drivers/misc/cxl/file.c +++ b/drivers/misc/cxl/file.c | |||
@@ -76,7 +76,7 @@ static int __afu_open(struct inode *inode, struct file *file, bool master) | |||
76 | if (!afu->current_mode) | 76 | if (!afu->current_mode) |
77 | goto err_put_afu; | 77 | goto err_put_afu; |
78 | 78 | ||
79 | if (!cxl_ops->link_ok(adapter)) { | 79 | if (!cxl_ops->link_ok(adapter, afu)) { |
80 | rc = -EIO; | 80 | rc = -EIO; |
81 | goto err_put_afu; | 81 | goto err_put_afu; |
82 | } | 82 | } |
@@ -257,7 +257,7 @@ long afu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
257 | if (ctx->status == CLOSED) | 257 | if (ctx->status == CLOSED) |
258 | return -EIO; | 258 | return -EIO; |
259 | 259 | ||
260 | if (!cxl_ops->link_ok(ctx->afu->adapter)) | 260 | if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) |
261 | return -EIO; | 261 | return -EIO; |
262 | 262 | ||
263 | pr_devel("afu_ioctl\n"); | 263 | pr_devel("afu_ioctl\n"); |
@@ -287,7 +287,7 @@ int afu_mmap(struct file *file, struct vm_area_struct *vm) | |||
287 | if (ctx->status != STARTED) | 287 | if (ctx->status != STARTED) |
288 | return -EIO; | 288 | return -EIO; |
289 | 289 | ||
290 | if (!cxl_ops->link_ok(ctx->afu->adapter)) | 290 | if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) |
291 | return -EIO; | 291 | return -EIO; |
292 | 292 | ||
293 | return cxl_context_iomap(ctx, vm); | 293 | return cxl_context_iomap(ctx, vm); |
@@ -334,7 +334,7 @@ ssize_t afu_read(struct file *file, char __user *buf, size_t count, | |||
334 | int rc; | 334 | int rc; |
335 | DEFINE_WAIT(wait); | 335 | DEFINE_WAIT(wait); |
336 | 336 | ||
337 | if (!cxl_ops->link_ok(ctx->afu->adapter)) | 337 | if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) |
338 | return -EIO; | 338 | return -EIO; |
339 | 339 | ||
340 | if (count < CXL_READ_MIN_SIZE) | 340 | if (count < CXL_READ_MIN_SIZE) |
@@ -347,7 +347,7 @@ ssize_t afu_read(struct file *file, char __user *buf, size_t count, | |||
347 | if (ctx_event_pending(ctx)) | 347 | if (ctx_event_pending(ctx)) |
348 | break; | 348 | break; |
349 | 349 | ||
350 | if (!cxl_ops->link_ok(ctx->afu->adapter)) { | 350 | if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) { |
351 | rc = -EIO; | 351 | rc = -EIO; |
352 | goto out; | 352 | goto out; |
353 | } | 353 | } |
diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c index 2b07ebd2b429..8213372de2b7 100644 --- a/drivers/misc/cxl/guest.c +++ b/drivers/misc/cxl/guest.c | |||
@@ -15,6 +15,46 @@ | |||
15 | #include "hcalls.h" | 15 | #include "hcalls.h" |
16 | #include "trace.h" | 16 | #include "trace.h" |
17 | 17 | ||
18 | #define CXL_ERROR_DETECTED_EVENT 1 | ||
19 | #define CXL_SLOT_RESET_EVENT 2 | ||
20 | #define CXL_RESUME_EVENT 3 | ||
21 | |||
22 | static void pci_error_handlers(struct cxl_afu *afu, | ||
23 | int bus_error_event, | ||
24 | pci_channel_state_t state) | ||
25 | { | ||
26 | struct pci_dev *afu_dev; | ||
27 | |||
28 | if (afu->phb == NULL) | ||
29 | return; | ||
30 | |||
31 | list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) { | ||
32 | if (!afu_dev->driver) | ||
33 | continue; | ||
34 | |||
35 | switch (bus_error_event) { | ||
36 | case CXL_ERROR_DETECTED_EVENT: | ||
37 | afu_dev->error_state = state; | ||
38 | |||
39 | if (afu_dev->driver->err_handler && | ||
40 | afu_dev->driver->err_handler->error_detected) | ||
41 | afu_dev->driver->err_handler->error_detected(afu_dev, state); | ||
42 | break; | ||
43 | case CXL_SLOT_RESET_EVENT: | ||
44 | afu_dev->error_state = state; | ||
45 | |||
46 | if (afu_dev->driver->err_handler && | ||
47 | afu_dev->driver->err_handler->slot_reset) | ||
48 | afu_dev->driver->err_handler->slot_reset(afu_dev); | ||
49 | break; | ||
50 | case CXL_RESUME_EVENT: | ||
51 | if (afu_dev->driver->err_handler && | ||
52 | afu_dev->driver->err_handler->resume) | ||
53 | afu_dev->driver->err_handler->resume(afu_dev); | ||
54 | break; | ||
55 | } | ||
56 | } | ||
57 | } | ||
18 | 58 | ||
19 | static irqreturn_t guest_handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, | 59 | static irqreturn_t guest_handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, |
20 | u64 errstat) | 60 | u64 errstat) |
@@ -133,6 +173,22 @@ static irqreturn_t guest_psl_irq(int irq, void *data) | |||
133 | return rc; | 173 | return rc; |
134 | } | 174 | } |
135 | 175 | ||
176 | static int afu_read_error_state(struct cxl_afu *afu, int *state_out) | ||
177 | { | ||
178 | u64 state; | ||
179 | int rc = 0; | ||
180 | |||
181 | rc = cxl_h_read_error_state(afu->guest->handle, &state); | ||
182 | if (!rc) { | ||
183 | WARN_ON(state != H_STATE_NORMAL && | ||
184 | state != H_STATE_DISABLE && | ||
185 | state != H_STATE_TEMP_UNAVAILABLE && | ||
186 | state != H_STATE_PERM_UNAVAILABLE); | ||
187 | *state_out = state & 0xffffffff; | ||
188 | } | ||
189 | return rc; | ||
190 | } | ||
191 | |||
136 | static irqreturn_t guest_slice_irq_err(int irq, void *data) | 192 | static irqreturn_t guest_slice_irq_err(int irq, void *data) |
137 | { | 193 | { |
138 | struct cxl_afu *afu = data; | 194 | struct cxl_afu *afu = data; |
@@ -201,10 +257,26 @@ static int irq_free_range(struct cxl *adapter, int irq, int len) | |||
201 | 257 | ||
202 | static int guest_reset(struct cxl *adapter) | 258 | static int guest_reset(struct cxl *adapter) |
203 | { | 259 | { |
204 | int rc; | 260 | struct cxl_afu *afu = NULL; |
261 | int i, rc; | ||
205 | 262 | ||
206 | pr_devel("Adapter reset request\n"); | 263 | pr_devel("Adapter reset request\n"); |
264 | for (i = 0; i < adapter->slices; i++) { | ||
265 | if ((afu = adapter->afu[i])) { | ||
266 | pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT, | ||
267 | pci_channel_io_frozen); | ||
268 | cxl_context_detach_all(afu); | ||
269 | } | ||
270 | } | ||
271 | |||
207 | rc = cxl_h_reset_adapter(adapter->guest->handle); | 272 | rc = cxl_h_reset_adapter(adapter->guest->handle); |
273 | for (i = 0; i < adapter->slices; i++) { | ||
274 | if (!rc && (afu = adapter->afu[i])) { | ||
275 | pci_error_handlers(afu, CXL_SLOT_RESET_EVENT, | ||
276 | pci_channel_io_normal); | ||
277 | pci_error_handlers(afu, CXL_RESUME_EVENT, 0); | ||
278 | } | ||
279 | } | ||
208 | return rc; | 280 | return rc; |
209 | } | 281 | } |
210 | 282 | ||
@@ -556,7 +628,7 @@ static int guest_detach_process(struct cxl_context *ctx) | |||
556 | pr_devel("in %s\n", __func__); | 628 | pr_devel("in %s\n", __func__); |
557 | trace_cxl_detach(ctx); | 629 | trace_cxl_detach(ctx); |
558 | 630 | ||
559 | if (!cxl_ops->link_ok(ctx->afu->adapter)) | 631 | if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) |
560 | return -EIO; | 632 | return -EIO; |
561 | 633 | ||
562 | if (ctx->afu->current_mode == CXL_MODE_DIRECTED) | 634 | if (ctx->afu->current_mode == CXL_MODE_DIRECTED) |
@@ -730,8 +802,95 @@ static void guest_unmap_slice_regs(struct cxl_afu *afu) | |||
730 | iounmap(afu->p2n_mmio); | 802 | iounmap(afu->p2n_mmio); |
731 | } | 803 | } |
732 | 804 | ||
733 | static bool guest_link_ok(struct cxl *cxl) | 805 | static int afu_update_state(struct cxl_afu *afu) |
734 | { | 806 | { |
807 | int rc, cur_state; | ||
808 | |||
809 | rc = afu_read_error_state(afu, &cur_state); | ||
810 | if (rc) | ||
811 | return rc; | ||
812 | |||
813 | if (afu->guest->previous_state == cur_state) | ||
814 | return 0; | ||
815 | |||
816 | pr_devel("AFU(%d) update state to %#x\n", afu->slice, cur_state); | ||
817 | |||
818 | switch (cur_state) { | ||
819 | case H_STATE_NORMAL: | ||
820 | afu->guest->previous_state = cur_state; | ||
821 | rc = 1; | ||
822 | break; | ||
823 | |||
824 | case H_STATE_DISABLE: | ||
825 | pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT, | ||
826 | pci_channel_io_frozen); | ||
827 | |||
828 | cxl_context_detach_all(afu); | ||
829 | if ((rc = cxl_ops->afu_reset(afu))) | ||
830 | pr_devel("reset hcall failed %d\n", rc); | ||
831 | |||
832 | rc = afu_read_error_state(afu, &cur_state); | ||
833 | if (!rc && cur_state == H_STATE_NORMAL) { | ||
834 | pci_error_handlers(afu, CXL_SLOT_RESET_EVENT, | ||
835 | pci_channel_io_normal); | ||
836 | pci_error_handlers(afu, CXL_RESUME_EVENT, 0); | ||
837 | rc = 1; | ||
838 | } | ||
839 | afu->guest->previous_state = 0; | ||
840 | break; | ||
841 | |||
842 | case H_STATE_TEMP_UNAVAILABLE: | ||
843 | afu->guest->previous_state = cur_state; | ||
844 | break; | ||
845 | |||
846 | case H_STATE_PERM_UNAVAILABLE: | ||
847 | dev_err(&afu->dev, "AFU is in permanent error state\n"); | ||
848 | pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT, | ||
849 | pci_channel_io_perm_failure); | ||
850 | afu->guest->previous_state = cur_state; | ||
851 | break; | ||
852 | |||
853 | default: | ||
854 | pr_err("Unexpected AFU(%d) error state: %#x\n", | ||
855 | afu->slice, cur_state); | ||
856 | return -EINVAL; | ||
857 | } | ||
858 | |||
859 | return rc; | ||
860 | } | ||
861 | |||
862 | static int afu_do_recovery(struct cxl_afu *afu) | ||
863 | { | ||
864 | int rc; | ||
865 | |||
866 | /* many threads can arrive here, in case of detach_all for example. | ||
867 | * Only one needs to drive the recovery | ||
868 | */ | ||
869 | if (mutex_trylock(&afu->guest->recovery_lock)) { | ||
870 | rc = afu_update_state(afu); | ||
871 | mutex_unlock(&afu->guest->recovery_lock); | ||
872 | return rc; | ||
873 | } | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static bool guest_link_ok(struct cxl *cxl, struct cxl_afu *afu) | ||
878 | { | ||
879 | int state; | ||
880 | |||
881 | if (afu) { | ||
882 | if (afu_read_error_state(afu, &state) || | ||
883 | state != H_STATE_NORMAL) { | ||
884 | if (afu_do_recovery(afu) > 0) { | ||
885 | /* check again in case we've just fixed it */ | ||
886 | if (!afu_read_error_state(afu, &state) && | ||
887 | state == H_STATE_NORMAL) | ||
888 | return true; | ||
889 | } | ||
890 | return false; | ||
891 | } | ||
892 | } | ||
893 | |||
735 | return true; | 894 | return true; |
736 | } | 895 | } |
737 | 896 | ||
@@ -770,6 +929,8 @@ int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_n | |||
770 | return -ENOMEM; | 929 | return -ENOMEM; |
771 | } | 930 | } |
772 | 931 | ||
932 | mutex_init(&afu->guest->recovery_lock); | ||
933 | |||
773 | if ((rc = dev_set_name(&afu->dev, "afu%i.%i", | 934 | if ((rc = dev_set_name(&afu->dev, "afu%i.%i", |
774 | adapter->adapter_num, | 935 | adapter->adapter_num, |
775 | slice))) | 936 | slice))) |
diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c index 14b15835dc4a..ae68c3201156 100644 --- a/drivers/misc/cxl/main.c +++ b/drivers/misc/cxl/main.c | |||
@@ -48,7 +48,7 @@ int cxl_afu_slbia(struct cxl_afu *afu) | |||
48 | /* If the adapter has gone down, we can assume that we | 48 | /* If the adapter has gone down, we can assume that we |
49 | * will PERST it and that will invalidate everything. | 49 | * will PERST it and that will invalidate everything. |
50 | */ | 50 | */ |
51 | if (!cxl_ops->link_ok(afu->adapter)) | 51 | if (!cxl_ops->link_ok(afu->adapter, afu)) |
52 | return -EIO; | 52 | return -EIO; |
53 | cpu_relax(); | 53 | cpu_relax(); |
54 | } | 54 | } |
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c index e564ae657584..387fcbdf9793 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_ops->link_ok(afu->adapter)) { | 45 | if (!cxl_ops->link_ok(afu->adapter, afu)) { |
46 | afu->enabled = enabled; | 46 | afu->enabled = enabled; |
47 | rc = -EIO; | 47 | rc = -EIO; |
48 | goto out; | 48 | goto out; |
@@ -92,7 +92,7 @@ static int native_afu_reset(struct cxl_afu *afu) | |||
92 | 92 | ||
93 | static int native_afu_check_and_enable(struct cxl_afu *afu) | 93 | static int native_afu_check_and_enable(struct cxl_afu *afu) |
94 | { | 94 | { |
95 | if (!cxl_ops->link_ok(afu->adapter)) { | 95 | if (!cxl_ops->link_ok(afu->adapter, afu)) { |
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_ops->link_ok(afu->adapter)) { | 117 | if (!cxl_ops->link_ok(afu->adapter, afu)) { |
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_ops->link_ok(afu->adapter)) { | 139 | if (!cxl_ops->link_ok(afu->adapter, afu)) { |
140 | rc = -EIO; | 140 | rc = -EIO; |
141 | goto out; | 141 | goto out; |
142 | } | 142 | } |
@@ -250,7 +250,7 @@ int cxl_tlb_slb_invalidate(struct cxl *adapter) | |||
250 | dev_warn(&adapter->dev, "WARNING: CXL adapter wide TLBIA timed out!\n"); | 250 | dev_warn(&adapter->dev, "WARNING: CXL adapter wide TLBIA timed out!\n"); |
251 | return -EBUSY; | 251 | return -EBUSY; |
252 | } | 252 | } |
253 | if (!cxl_ops->link_ok(adapter)) | 253 | if (!cxl_ops->link_ok(adapter, NULL)) |
254 | return -EIO; | 254 | return -EIO; |
255 | cpu_relax(); | 255 | cpu_relax(); |
256 | } | 256 | } |
@@ -261,7 +261,7 @@ int cxl_tlb_slb_invalidate(struct cxl *adapter) | |||
261 | dev_warn(&adapter->dev, "WARNING: CXL adapter wide SLBIA timed out!\n"); | 261 | dev_warn(&adapter->dev, "WARNING: CXL adapter wide SLBIA timed out!\n"); |
262 | return -EBUSY; | 262 | return -EBUSY; |
263 | } | 263 | } |
264 | if (!cxl_ops->link_ok(adapter)) | 264 | if (!cxl_ops->link_ok(adapter, NULL)) |
265 | return -EIO; | 265 | return -EIO; |
266 | cpu_relax(); | 266 | cpu_relax(); |
267 | } | 267 | } |
@@ -302,7 +302,7 @@ static void slb_invalid(struct cxl_context *ctx) | |||
302 | cxl_p1_write(adapter, CXL_PSL_SLBIA, CXL_TLB_SLB_IQ_LPIDPID); | 302 | cxl_p1_write(adapter, CXL_PSL_SLBIA, CXL_TLB_SLB_IQ_LPIDPID); |
303 | 303 | ||
304 | while (1) { | 304 | while (1) { |
305 | if (!cxl_ops->link_ok(adapter)) | 305 | if (!cxl_ops->link_ok(adapter, NULL)) |
306 | break; | 306 | break; |
307 | slbia = cxl_p1_read(adapter, CXL_PSL_SLBIA); | 307 | slbia = cxl_p1_read(adapter, CXL_PSL_SLBIA); |
308 | if (!(slbia & CXL_TLB_SLB_P)) | 308 | if (!(slbia & CXL_TLB_SLB_P)) |
@@ -333,7 +333,7 @@ static int do_process_element_cmd(struct cxl_context *ctx, | |||
333 | rc = -EBUSY; | 333 | rc = -EBUSY; |
334 | goto out; | 334 | goto out; |
335 | } | 335 | } |
336 | if (!cxl_ops->link_ok(ctx->afu->adapter)) { | 336 | if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) { |
337 | dev_warn(&ctx->afu->dev, "WARNING: Device link down, aborting Process Element Command!\n"); | 337 | dev_warn(&ctx->afu->dev, "WARNING: Device link down, aborting Process Element Command!\n"); |
338 | rc = -EIO; | 338 | rc = -EIO; |
339 | goto out; | 339 | goto out; |
@@ -389,7 +389,7 @@ static int terminate_process_element(struct cxl_context *ctx) | |||
389 | * should always succeed: it's not running if the hw has gone | 389 | * should always succeed: it's not running if the hw has gone |
390 | * away and is being reset. | 390 | * away and is being reset. |
391 | */ | 391 | */ |
392 | if (cxl_ops->link_ok(ctx->afu->adapter)) | 392 | if (cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) |
393 | rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_TERMINATE, | 393 | rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_TERMINATE, |
394 | CXL_PE_SOFTWARE_STATE_V | CXL_PE_SOFTWARE_STATE_T); | 394 | CXL_PE_SOFTWARE_STATE_V | CXL_PE_SOFTWARE_STATE_T); |
395 | ctx->elem->software_state = 0; /* Remove Valid bit */ | 395 | ctx->elem->software_state = 0; /* Remove Valid bit */ |
@@ -408,7 +408,7 @@ static int remove_process_element(struct cxl_context *ctx) | |||
408 | /* We could be asked to remove when the hw is down. Again, if | 408 | /* We could be asked to remove when the hw is down. Again, if |
409 | * the hw is down, the PE is gone, so we succeed. | 409 | * the hw is down, the PE is gone, so we succeed. |
410 | */ | 410 | */ |
411 | if (cxl_ops->link_ok(ctx->afu->adapter)) | 411 | if (cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) |
412 | rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_REMOVE, 0); | 412 | rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_REMOVE, 0); |
413 | 413 | ||
414 | if (!rc) | 414 | if (!rc) |
@@ -650,7 +650,7 @@ static int native_afu_activate_mode(struct cxl_afu *afu, int mode) | |||
650 | if (!(mode & afu->modes_supported)) | 650 | if (!(mode & afu->modes_supported)) |
651 | return -EINVAL; | 651 | return -EINVAL; |
652 | 652 | ||
653 | if (!cxl_ops->link_ok(afu->adapter)) { | 653 | if (!cxl_ops->link_ok(afu->adapter, afu)) { |
654 | WARN(1, "Device link is down, refusing to activate!\n"); | 654 | WARN(1, "Device link is down, refusing to activate!\n"); |
655 | return -EIO; | 655 | return -EIO; |
656 | } | 656 | } |
@@ -666,7 +666,7 @@ static int native_afu_activate_mode(struct cxl_afu *afu, int mode) | |||
666 | static int native_attach_process(struct cxl_context *ctx, bool kernel, | 666 | static int native_attach_process(struct cxl_context *ctx, bool kernel, |
667 | u64 wed, u64 amr) | 667 | u64 wed, u64 amr) |
668 | { | 668 | { |
669 | if (!cxl_ops->link_ok(ctx->afu->adapter)) { | 669 | if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) { |
670 | WARN(1, "Device link is down, refusing to attach process!\n"); | 670 | WARN(1, "Device link is down, refusing to attach process!\n"); |
671 | return -EIO; | 671 | return -EIO; |
672 | } | 672 | } |
@@ -718,7 +718,7 @@ static int native_get_irq_info(struct cxl_afu *afu, struct cxl_irq_info *info) | |||
718 | /* If the adapter has gone away, we can't get any meaningful | 718 | /* If the adapter has gone away, we can't get any meaningful |
719 | * information. | 719 | * information. |
720 | */ | 720 | */ |
721 | if (!cxl_ops->link_ok(afu->adapter)) | 721 | if (!cxl_ops->link_ok(afu->adapter, afu)) |
722 | return -EIO; | 722 | return -EIO; |
723 | 723 | ||
724 | info->dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); | 724 | info->dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); |
@@ -975,7 +975,7 @@ static bool native_support_attributes(const char *attr_name, | |||
975 | 975 | ||
976 | static int native_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off, u64 *out) | 976 | static int native_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off, u64 *out) |
977 | { | 977 | { |
978 | if (unlikely(!cxl_ops->link_ok(afu->adapter))) | 978 | if (unlikely(!cxl_ops->link_ok(afu->adapter, afu))) |
979 | return -EIO; | 979 | return -EIO; |
980 | if (unlikely(off >= afu->crs_len)) | 980 | if (unlikely(off >= afu->crs_len)) |
981 | return -ERANGE; | 981 | return -ERANGE; |
@@ -986,7 +986,7 @@ static int native_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off, u64 *out) | |||
986 | 986 | ||
987 | static int native_afu_cr_read32(struct cxl_afu *afu, int cr, u64 off, u32 *out) | 987 | static int native_afu_cr_read32(struct cxl_afu *afu, int cr, u64 off, u32 *out) |
988 | { | 988 | { |
989 | if (unlikely(!cxl_ops->link_ok(afu->adapter))) | 989 | if (unlikely(!cxl_ops->link_ok(afu->adapter, afu))) |
990 | return -EIO; | 990 | return -EIO; |
991 | if (unlikely(off >= afu->crs_len)) | 991 | if (unlikely(off >= afu->crs_len)) |
992 | return -ERANGE; | 992 | return -ERANGE; |
@@ -1021,7 +1021,7 @@ static int native_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off, u8 *out) | |||
1021 | 1021 | ||
1022 | static int native_afu_cr_write32(struct cxl_afu *afu, int cr, u64 off, u32 in) | 1022 | static int native_afu_cr_write32(struct cxl_afu *afu, int cr, u64 off, u32 in) |
1023 | { | 1023 | { |
1024 | if (unlikely(!cxl_ops->link_ok(afu->adapter))) | 1024 | if (unlikely(!cxl_ops->link_ok(afu->adapter, afu))) |
1025 | return -EIO; | 1025 | return -EIO; |
1026 | if (unlikely(off >= afu->crs_len)) | 1026 | if (unlikely(off >= afu->crs_len)) |
1027 | return -ERANGE; | 1027 | return -ERANGE; |
diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c index c960a09a4232..490b93486451 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_ops->link_ok(afu->adapter)) { | 52 | if (!cxl_ops->link_ok(afu->adapter, afu)) { |
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 | } |