diff options
author | Mitko Haralanov <mitko.haralanov@intel.com> | 2016-03-08 14:14:48 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-03-21 15:55:22 -0400 |
commit | 909e2cd004b639276678c195760efeea6c173626 (patch) | |
tree | 0b01ddca0e0eec9972888160608e01a6d7da8f51 | |
parent | 368f2b59d024fbb58015dfd0e09c54c424cda979 (diff) |
IB/hfi1: Notify remove MMU/RB callback of calling context
Tell the remove MMU/RB callback if it's being called as
part of a memory invalidation or not. This can be important
in preventing a deadlock if the remove callback attempts to
take the map_sem semaphore because the kernel's MMU
invalidation functions have already taken it.
Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Reviewed-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: Jubin John <jubin.john@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/staging/rdma/hfi1/mmu_rb.c | 10 | ||||
-rw-r--r-- | drivers/staging/rdma/hfi1/mmu_rb.h | 2 | ||||
-rw-r--r-- | drivers/staging/rdma/hfi1/user_exp_rcv.c | 9 |
3 files changed, 11 insertions, 10 deletions
diff --git a/drivers/staging/rdma/hfi1/mmu_rb.c b/drivers/staging/rdma/hfi1/mmu_rb.c index a3515d7f6354..29d6d3e0694d 100644 --- a/drivers/staging/rdma/hfi1/mmu_rb.c +++ b/drivers/staging/rdma/hfi1/mmu_rb.c | |||
@@ -122,7 +122,7 @@ void hfi1_mmu_rb_unregister(struct rb_root *root) | |||
122 | rbnode = rb_entry(node, struct mmu_rb_node, node); | 122 | rbnode = rb_entry(node, struct mmu_rb_node, node); |
123 | rb_erase(node, root); | 123 | rb_erase(node, root); |
124 | if (handler->ops->remove) | 124 | if (handler->ops->remove) |
125 | handler->ops->remove(root, rbnode); | 125 | handler->ops->remove(root, rbnode, false); |
126 | } | 126 | } |
127 | } | 127 | } |
128 | 128 | ||
@@ -196,12 +196,12 @@ static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler, | |||
196 | } | 196 | } |
197 | 197 | ||
198 | static void __mmu_rb_remove(struct mmu_rb_handler *handler, | 198 | static void __mmu_rb_remove(struct mmu_rb_handler *handler, |
199 | struct mmu_rb_node *node) | 199 | struct mmu_rb_node *node, bool arg) |
200 | { | 200 | { |
201 | /* Validity of handler and node pointers has been checked by caller. */ | 201 | /* Validity of handler and node pointers has been checked by caller. */ |
202 | rb_erase(&node->node, handler->root); | 202 | rb_erase(&node->node, handler->root); |
203 | if (handler->ops->remove) | 203 | if (handler->ops->remove) |
204 | handler->ops->remove(handler->root, node); | 204 | handler->ops->remove(handler->root, node, arg); |
205 | } | 205 | } |
206 | 206 | ||
207 | struct mmu_rb_node *hfi1_mmu_rb_search(struct rb_root *root, unsigned long addr, | 207 | struct mmu_rb_node *hfi1_mmu_rb_search(struct rb_root *root, unsigned long addr, |
@@ -230,7 +230,7 @@ void hfi1_mmu_rb_remove(struct rb_root *root, struct mmu_rb_node *node) | |||
230 | return; | 230 | return; |
231 | 231 | ||
232 | spin_lock_irqsave(&handler->lock, flags); | 232 | spin_lock_irqsave(&handler->lock, flags); |
233 | __mmu_rb_remove(handler, node); | 233 | __mmu_rb_remove(handler, node, false); |
234 | spin_unlock_irqrestore(&handler->lock, flags); | 234 | spin_unlock_irqrestore(&handler->lock, flags); |
235 | } | 235 | } |
236 | 236 | ||
@@ -299,7 +299,7 @@ static void mmu_notifier_mem_invalidate(struct mmu_notifier *mn, | |||
299 | naddr = node->addr; | 299 | naddr = node->addr; |
300 | nlen = node->len; | 300 | nlen = node->len; |
301 | if (handler->ops->invalidate(root, node)) | 301 | if (handler->ops->invalidate(root, node)) |
302 | __mmu_rb_remove(handler, node); | 302 | __mmu_rb_remove(handler, node, true); |
303 | 303 | ||
304 | /* | 304 | /* |
305 | * The next address to be looked up is computed based | 305 | * The next address to be looked up is computed based |
diff --git a/drivers/staging/rdma/hfi1/mmu_rb.h b/drivers/staging/rdma/hfi1/mmu_rb.h index 9fe1076ab39d..fdd978757b90 100644 --- a/drivers/staging/rdma/hfi1/mmu_rb.h +++ b/drivers/staging/rdma/hfi1/mmu_rb.h | |||
@@ -59,7 +59,7 @@ struct mmu_rb_ops { | |||
59 | int (*compare)(struct mmu_rb_node *, unsigned long, | 59 | int (*compare)(struct mmu_rb_node *, unsigned long, |
60 | unsigned long); | 60 | unsigned long); |
61 | int (*insert)(struct rb_root *, struct mmu_rb_node *); | 61 | int (*insert)(struct rb_root *, struct mmu_rb_node *); |
62 | void (*remove)(struct rb_root *, struct mmu_rb_node *); | 62 | void (*remove)(struct rb_root *, struct mmu_rb_node *, bool); |
63 | int (*invalidate)(struct rb_root *, struct mmu_rb_node *); | 63 | int (*invalidate)(struct rb_root *, struct mmu_rb_node *); |
64 | }; | 64 | }; |
65 | 65 | ||
diff --git a/drivers/staging/rdma/hfi1/user_exp_rcv.c b/drivers/staging/rdma/hfi1/user_exp_rcv.c index b0b193f30fac..1d971c0fedd6 100644 --- a/drivers/staging/rdma/hfi1/user_exp_rcv.c +++ b/drivers/staging/rdma/hfi1/user_exp_rcv.c | |||
@@ -89,7 +89,7 @@ static int set_rcvarray_entry(struct file *, unsigned long, u32, | |||
89 | static inline int mmu_addr_cmp(struct mmu_rb_node *, unsigned long, | 89 | static inline int mmu_addr_cmp(struct mmu_rb_node *, unsigned long, |
90 | unsigned long); | 90 | unsigned long); |
91 | static int mmu_rb_insert(struct rb_root *, struct mmu_rb_node *); | 91 | static int mmu_rb_insert(struct rb_root *, struct mmu_rb_node *); |
92 | static void mmu_rb_remove(struct rb_root *, struct mmu_rb_node *); | 92 | static void mmu_rb_remove(struct rb_root *, struct mmu_rb_node *, bool); |
93 | static int mmu_rb_invalidate(struct rb_root *, struct mmu_rb_node *); | 93 | static int mmu_rb_invalidate(struct rb_root *, struct mmu_rb_node *); |
94 | static int program_rcvarray(struct file *, unsigned long, struct tid_group *, | 94 | static int program_rcvarray(struct file *, unsigned long, struct tid_group *, |
95 | struct tid_pageset *, unsigned, u16, struct page **, | 95 | struct tid_pageset *, unsigned, u16, struct page **, |
@@ -897,7 +897,7 @@ static int unprogram_rcvarray(struct file *fp, u32 tidinfo, | |||
897 | if (!node || node->rcventry != (uctxt->expected_base + rcventry)) | 897 | if (!node || node->rcventry != (uctxt->expected_base + rcventry)) |
898 | return -EBADF; | 898 | return -EBADF; |
899 | if (HFI1_CAP_IS_USET(TID_UNMAP)) | 899 | if (HFI1_CAP_IS_USET(TID_UNMAP)) |
900 | mmu_rb_remove(&fd->tid_rb_root, &node->mmu); | 900 | mmu_rb_remove(&fd->tid_rb_root, &node->mmu, false); |
901 | else | 901 | else |
902 | hfi1_mmu_rb_remove(&fd->tid_rb_root, &node->mmu); | 902 | hfi1_mmu_rb_remove(&fd->tid_rb_root, &node->mmu); |
903 | 903 | ||
@@ -962,7 +962,7 @@ static void unlock_exp_tids(struct hfi1_ctxtdata *uctxt, | |||
962 | continue; | 962 | continue; |
963 | if (HFI1_CAP_IS_USET(TID_UNMAP)) | 963 | if (HFI1_CAP_IS_USET(TID_UNMAP)) |
964 | mmu_rb_remove(&fd->tid_rb_root, | 964 | mmu_rb_remove(&fd->tid_rb_root, |
965 | &node->mmu); | 965 | &node->mmu, false); |
966 | else | 966 | else |
967 | hfi1_mmu_rb_remove(&fd->tid_rb_root, | 967 | hfi1_mmu_rb_remove(&fd->tid_rb_root, |
968 | &node->mmu); | 968 | &node->mmu); |
@@ -1039,7 +1039,8 @@ static int mmu_rb_insert(struct rb_root *root, struct mmu_rb_node *node) | |||
1039 | return 0; | 1039 | return 0; |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | static void mmu_rb_remove(struct rb_root *root, struct mmu_rb_node *node) | 1042 | static void mmu_rb_remove(struct rb_root *root, struct mmu_rb_node *node, |
1043 | bool notifier) | ||
1043 | { | 1044 | { |
1044 | struct hfi1_filedata *fdata = | 1045 | struct hfi1_filedata *fdata = |
1045 | container_of(root, struct hfi1_filedata, tid_rb_root); | 1046 | container_of(root, struct hfi1_filedata, tid_rb_root); |