]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | Subject: [PATCH]IB/ehca:reject dynamic memory add/remove |
2 | From: Stefan Roscher <ossrosch@linux.vnet.ibm.com> | |
3 | References: 434651 - LTC48744 | |
4 | ||
5 | Since the ehca device driver does not support dynamic memory add and remove | |
6 | operations, the driver must explicitly reject such requests in order to prevent | |
7 | unpredictable behaviors related to memory regions already occupied and being | |
8 | used by InfiniBand applications. | |
9 | The solution is to add a memory notifier to the ehca device driver and if a request | |
10 | for dynamic memory add or remove comes in, ehca will always reject it. | |
11 | ||
12 | Signed-off-by: Stefan Roscher <stefan.roscher@de.ibm.com> | |
13 | Signed-off-by: Olaf Hering <olh@suse.de> | |
14 | ||
15 | --- | |
16 | drivers/infiniband/hw/ehca/ehca_main.c | 46 +++++++++++++++++++++++++++++++++ | |
17 | 1 file changed, 46 insertions(+) | |
18 | ||
19 | --- a/drivers/infiniband/hw/ehca/ehca_main.c | |
20 | +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |
21 | @@ -44,6 +44,8 @@ | |
22 | #include <linux/slab.h> | |
23 | #endif | |
24 | ||
25 | +#include <linux/notifier.h> | |
26 | +#include <linux/memory.h> | |
27 | #include "ehca_classes.h" | |
28 | #include "ehca_iverbs.h" | |
29 | #include "ehca_mrmw.h" | |
30 | @@ -965,6 +967,39 @@ void ehca_poll_eqs(unsigned long data) | |
31 | spin_unlock(&shca_list_lock); | |
32 | } | |
33 | ||
34 | +static int ehca_mem_notifier(struct notifier_block *nb, | |
35 | + unsigned long action, void *data) | |
36 | +{ | |
37 | + static unsigned long ehca_dmem_warn_time; | |
38 | + | |
39 | + switch (action) { | |
40 | + case MEM_CANCEL_OFFLINE: | |
41 | + case MEM_CANCEL_ONLINE: | |
42 | + case MEM_ONLINE: | |
43 | + case MEM_OFFLINE: | |
44 | + return NOTIFY_OK; | |
45 | + case MEM_GOING_ONLINE: | |
46 | + case MEM_GOING_OFFLINE: | |
47 | + /* only ok if no hca is attached to the lpar */ | |
48 | + spin_lock(&shca_list_lock); | |
49 | + if (list_empty(&shca_list)) { | |
50 | + spin_unlock(&shca_list_lock); | |
51 | + return NOTIFY_OK; | |
52 | + } else { | |
53 | + spin_unlock(&shca_list_lock); | |
54 | + if (printk_timed_ratelimit(&ehca_dmem_warn_time, | |
55 | + 30 * 1000)) | |
56 | + ehca_gen_err("DMEM operations are not allowed in conjunction with eHCA"); | |
57 | + return NOTIFY_BAD; | |
58 | + } | |
59 | + } | |
60 | + return NOTIFY_OK; | |
61 | +} | |
62 | + | |
63 | +static struct notifier_block ehca_mem_nb = { | |
64 | + .notifier_call = ehca_mem_notifier, | |
65 | +}; | |
66 | + | |
67 | static int __init ehca_module_init(void) | |
68 | { | |
69 | int ret; | |
70 | @@ -992,6 +1027,12 @@ static int __init ehca_module_init(void) | |
71 | goto module_init2; | |
72 | } | |
73 | ||
74 | + ret = register_memory_notifier(&ehca_mem_nb); | |
75 | + if (ret) { | |
76 | + ehca_gen_err("Failed registering memory add/remove notifier"); | |
77 | + goto module_init3; | |
78 | + } | |
79 | + | |
80 | if (ehca_poll_all_eqs != 1) { | |
81 | ehca_gen_err("WARNING!!!"); | |
82 | ehca_gen_err("It is possible to lose interrupts."); | |
83 | @@ -1004,6 +1045,9 @@ static int __init ehca_module_init(void) | |
84 | ||
85 | return 0; | |
86 | ||
87 | +module_init3: | |
88 | + ibmebus_unregister_driver(&ehca_driver); | |
89 | + | |
90 | module_init2: | |
91 | ehca_destroy_slab_caches(); | |
92 | ||
93 | @@ -1019,6 +1063,8 @@ static void __exit ehca_module_exit(void | |
94 | ||
95 | ibmebus_unregister_driver(&ehca_driver); | |
96 | ||
97 | + unregister_memory_notifier(&ehca_mem_nb); | |
98 | + | |
99 | ehca_destroy_slab_caches(); | |
100 | ||
101 | ehca_destroy_comp_pool(); |