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); |
