diff options
author | Naresh Gottumukkala <bgottumukkala@emulex.com> | 2013-09-06 05:32:47 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-11-08 17:43:06 -0500 |
commit | 1852d1da3b4723d7db0d490f54c07442b3e1c452 (patch) | |
tree | 431dbd1132b59578a8ea153ffb863fb22f30b3a9 | |
parent | 6ebacdfc07ca61ba258693c9b4c88f1ffbe8ccd7 (diff) |
RDMA/ocrdma: Fix a crash in rmmod
1) ocrdma_remove_free() is called from a call_rcu callback funtion
context, which can be a bottom-half context. So the code in
ocrdma_remove_free should not sleep.
But ocrdma_cleanup_hw() can sleep, So move it ocrdma_remove()
instead of ocrdma_remove_free.
2) Fix a couple of kbuild test robot warnings.
Signed-off-by: Naresh Gottumukkala <bgottumukkala@emulex.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma.h | 53 | ||||
-rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_main.c | 7 | ||||
-rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 2 |
3 files changed, 32 insertions, 30 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index adc11d14f878..294dd27b601e 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h | |||
@@ -122,6 +122,32 @@ struct mqe_ctx { | |||
122 | bool cmd_done; | 122 | bool cmd_done; |
123 | }; | 123 | }; |
124 | 124 | ||
125 | struct ocrdma_hw_mr { | ||
126 | u32 lkey; | ||
127 | u8 fr_mr; | ||
128 | u8 remote_atomic; | ||
129 | u8 remote_rd; | ||
130 | u8 remote_wr; | ||
131 | u8 local_rd; | ||
132 | u8 local_wr; | ||
133 | u8 mw_bind; | ||
134 | u8 rsvd; | ||
135 | u64 len; | ||
136 | struct ocrdma_pbl *pbl_table; | ||
137 | u32 num_pbls; | ||
138 | u32 num_pbes; | ||
139 | u32 pbl_size; | ||
140 | u32 pbe_size; | ||
141 | u64 fbo; | ||
142 | u64 va; | ||
143 | }; | ||
144 | |||
145 | struct ocrdma_mr { | ||
146 | struct ib_mr ibmr; | ||
147 | struct ib_umem *umem; | ||
148 | struct ocrdma_hw_mr hwmr; | ||
149 | }; | ||
150 | |||
125 | struct ocrdma_dev { | 151 | struct ocrdma_dev { |
126 | struct ib_device ibdev; | 152 | struct ib_device ibdev; |
127 | struct ocrdma_dev_attr attr; | 153 | struct ocrdma_dev_attr attr; |
@@ -169,7 +195,7 @@ struct ocrdma_dev { | |||
169 | struct list_head entry; | 195 | struct list_head entry; |
170 | struct rcu_head rcu; | 196 | struct rcu_head rcu; |
171 | int id; | 197 | int id; |
172 | u64 stag_arr[OCRDMA_MAX_STAG]; | 198 | struct ocrdma_mr *stag_arr[OCRDMA_MAX_STAG]; |
173 | u16 pvid; | 199 | u16 pvid; |
174 | }; | 200 | }; |
175 | 201 | ||
@@ -294,31 +320,6 @@ struct ocrdma_qp { | |||
294 | u16 db_cache; | 320 | u16 db_cache; |
295 | }; | 321 | }; |
296 | 322 | ||
297 | struct ocrdma_hw_mr { | ||
298 | u32 lkey; | ||
299 | u8 fr_mr; | ||
300 | u8 remote_atomic; | ||
301 | u8 remote_rd; | ||
302 | u8 remote_wr; | ||
303 | u8 local_rd; | ||
304 | u8 local_wr; | ||
305 | u8 mw_bind; | ||
306 | u8 rsvd; | ||
307 | u64 len; | ||
308 | struct ocrdma_pbl *pbl_table; | ||
309 | u32 num_pbls; | ||
310 | u32 num_pbes; | ||
311 | u32 pbl_size; | ||
312 | u32 pbe_size; | ||
313 | u64 fbo; | ||
314 | u64 va; | ||
315 | }; | ||
316 | |||
317 | struct ocrdma_mr { | ||
318 | struct ib_mr ibmr; | ||
319 | struct ib_umem *umem; | ||
320 | struct ocrdma_hw_mr hwmr; | ||
321 | }; | ||
322 | 323 | ||
323 | struct ocrdma_ucontext { | 324 | struct ocrdma_ucontext { |
324 | struct ib_ucontext ibucontext; | 325 | struct ib_ucontext ibucontext; |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 0ce7674621ea..91443bcb9e0e 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c | |||
@@ -452,9 +452,6 @@ static void ocrdma_remove_free(struct rcu_head *rcu) | |||
452 | { | 452 | { |
453 | struct ocrdma_dev *dev = container_of(rcu, struct ocrdma_dev, rcu); | 453 | struct ocrdma_dev *dev = container_of(rcu, struct ocrdma_dev, rcu); |
454 | 454 | ||
455 | ocrdma_free_resources(dev); | ||
456 | ocrdma_cleanup_hw(dev); | ||
457 | |||
458 | idr_remove(&ocrdma_dev_id, dev->id); | 455 | idr_remove(&ocrdma_dev_id, dev->id); |
459 | kfree(dev->mbx_cmd); | 456 | kfree(dev->mbx_cmd); |
460 | ib_dealloc_device(&dev->ibdev); | 457 | ib_dealloc_device(&dev->ibdev); |
@@ -470,6 +467,10 @@ static void ocrdma_remove(struct ocrdma_dev *dev) | |||
470 | spin_lock(&ocrdma_devlist_lock); | 467 | spin_lock(&ocrdma_devlist_lock); |
471 | list_del_rcu(&dev->entry); | 468 | list_del_rcu(&dev->entry); |
472 | spin_unlock(&ocrdma_devlist_lock); | 469 | spin_unlock(&ocrdma_devlist_lock); |
470 | |||
471 | ocrdma_free_resources(dev); | ||
472 | ocrdma_cleanup_hw(dev); | ||
473 | |||
473 | call_rcu(&dev->rcu, ocrdma_remove_free); | 474 | call_rcu(&dev->rcu, ocrdma_remove_free); |
474 | } | 475 | } |
475 | 476 | ||
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 69f1d1221a6b..d4fbf916d3cc 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | |||
@@ -2839,7 +2839,7 @@ struct ib_mr *ocrdma_alloc_frmr(struct ib_pd *ibpd, int max_page_list_len) | |||
2839 | goto mbx_err; | 2839 | goto mbx_err; |
2840 | mr->ibmr.rkey = mr->hwmr.lkey; | 2840 | mr->ibmr.rkey = mr->hwmr.lkey; |
2841 | mr->ibmr.lkey = mr->hwmr.lkey; | 2841 | mr->ibmr.lkey = mr->hwmr.lkey; |
2842 | dev->stag_arr[(mr->hwmr.lkey >> 8) & (OCRDMA_MAX_STAG - 1)] = (unsigned long) mr; | 2842 | dev->stag_arr[(mr->hwmr.lkey >> 8) & (OCRDMA_MAX_STAG - 1)] = mr; |
2843 | return &mr->ibmr; | 2843 | return &mr->ibmr; |
2844 | mbx_err: | 2844 | mbx_err: |
2845 | ocrdma_free_mr_pbl_tbl(dev, &mr->hwmr); | 2845 | ocrdma_free_mr_pbl_tbl(dev, &mr->hwmr); |