diff options
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_main.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 086959a0cbee..bb02a86aa526 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -44,6 +44,8 @@ | |||
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #include <linux/notifier.h> | ||
48 | #include <linux/memory.h> | ||
47 | #include "ehca_classes.h" | 49 | #include "ehca_classes.h" |
48 | #include "ehca_iverbs.h" | 50 | #include "ehca_iverbs.h" |
49 | #include "ehca_mrmw.h" | 51 | #include "ehca_mrmw.h" |
@@ -969,6 +971,41 @@ void ehca_poll_eqs(unsigned long data) | |||
969 | spin_unlock(&shca_list_lock); | 971 | spin_unlock(&shca_list_lock); |
970 | } | 972 | } |
971 | 973 | ||
974 | static int ehca_mem_notifier(struct notifier_block *nb, | ||
975 | unsigned long action, void *data) | ||
976 | { | ||
977 | static unsigned long ehca_dmem_warn_time; | ||
978 | |||
979 | switch (action) { | ||
980 | case MEM_CANCEL_OFFLINE: | ||
981 | case MEM_CANCEL_ONLINE: | ||
982 | case MEM_ONLINE: | ||
983 | case MEM_OFFLINE: | ||
984 | return NOTIFY_OK; | ||
985 | case MEM_GOING_ONLINE: | ||
986 | case MEM_GOING_OFFLINE: | ||
987 | /* only ok if no hca is attached to the lpar */ | ||
988 | spin_lock(&shca_list_lock); | ||
989 | if (list_empty(&shca_list)) { | ||
990 | spin_unlock(&shca_list_lock); | ||
991 | return NOTIFY_OK; | ||
992 | } else { | ||
993 | spin_unlock(&shca_list_lock); | ||
994 | if (printk_timed_ratelimit(&ehca_dmem_warn_time, | ||
995 | 30 * 1000)) | ||
996 | ehca_gen_err("DMEM operations are not allowed" | ||
997 | "as long as an ehca adapter is" | ||
998 | "attached to the LPAR"); | ||
999 | return NOTIFY_BAD; | ||
1000 | } | ||
1001 | } | ||
1002 | return NOTIFY_OK; | ||
1003 | } | ||
1004 | |||
1005 | static struct notifier_block ehca_mem_nb = { | ||
1006 | .notifier_call = ehca_mem_notifier, | ||
1007 | }; | ||
1008 | |||
972 | static int __init ehca_module_init(void) | 1009 | static int __init ehca_module_init(void) |
973 | { | 1010 | { |
974 | int ret; | 1011 | int ret; |
@@ -996,6 +1033,12 @@ static int __init ehca_module_init(void) | |||
996 | goto module_init2; | 1033 | goto module_init2; |
997 | } | 1034 | } |
998 | 1035 | ||
1036 | ret = register_memory_notifier(&ehca_mem_nb); | ||
1037 | if (ret) { | ||
1038 | ehca_gen_err("Failed registering memory add/remove notifier"); | ||
1039 | goto module_init3; | ||
1040 | } | ||
1041 | |||
999 | if (ehca_poll_all_eqs != 1) { | 1042 | if (ehca_poll_all_eqs != 1) { |
1000 | ehca_gen_err("WARNING!!!"); | 1043 | ehca_gen_err("WARNING!!!"); |
1001 | ehca_gen_err("It is possible to lose interrupts."); | 1044 | ehca_gen_err("It is possible to lose interrupts."); |
@@ -1008,6 +1051,9 @@ static int __init ehca_module_init(void) | |||
1008 | 1051 | ||
1009 | return 0; | 1052 | return 0; |
1010 | 1053 | ||
1054 | module_init3: | ||
1055 | ibmebus_unregister_driver(&ehca_driver); | ||
1056 | |||
1011 | module_init2: | 1057 | module_init2: |
1012 | ehca_destroy_slab_caches(); | 1058 | ehca_destroy_slab_caches(); |
1013 | 1059 | ||
@@ -1023,6 +1069,8 @@ static void __exit ehca_module_exit(void) | |||
1023 | 1069 | ||
1024 | ibmebus_unregister_driver(&ehca_driver); | 1070 | ibmebus_unregister_driver(&ehca_driver); |
1025 | 1071 | ||
1072 | unregister_memory_notifier(&ehca_mem_nb); | ||
1073 | |||
1026 | ehca_destroy_slab_caches(); | 1074 | ehca_destroy_slab_caches(); |
1027 | 1075 | ||
1028 | ehca_destroy_comp_pool(); | 1076 | ehca_destroy_comp_pool(); |