aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/cma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core/cma.c')
-rw-r--r--drivers/infiniband/core/cma.c162
1 files changed, 81 insertions, 81 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 671f1373805..ae11d5cc74d 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -4,29 +4,33 @@
4 * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved. 4 * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
5 * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. 5 * Copyright (c) 2005-2006 Intel Corporation. All rights reserved.
6 * 6 *
7 * This Software is licensed under one of the following licenses: 7 * This software is available to you under a choice of one of two
8 * licenses. You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directory of this source tree, or the
11 * OpenIB.org BSD license below:
8 * 12 *
9 * 1) under the terms of the "Common Public License 1.0" a copy of which is 13 * Redistribution and use in source and binary forms, with or
10 * available from the Open Source Initiative, see 14 * without modification, are permitted provided that the following
11 * http://www.opensource.org/licenses/cpl.php. 15 * conditions are met:
12 * 16 *
13 * 2) under the terms of the "The BSD License" a copy of which is 17 * - Redistributions of source code must retain the above
14 * available from the Open Source Initiative, see 18 * copyright notice, this list of conditions and the following
15 * http://www.opensource.org/licenses/bsd-license.php. 19 * disclaimer.
16 * 20 *
17 * 3) under the terms of the "GNU General Public License (GPL) Version 2" a 21 * - Redistributions in binary form must reproduce the above
18 * copy of which is available from the Open Source Initiative, see 22 * copyright notice, this list of conditions and the following
19 * http://www.opensource.org/licenses/gpl-license.php. 23 * disclaimer in the documentation and/or other materials
20 * 24 * provided with the distribution.
21 * Licensee has the right to choose one of the above licenses.
22 *
23 * Redistributions of source code must retain the above copyright
24 * notice and one of the license notices.
25 *
26 * Redistributions in binary form must reproduce both the above copyright
27 * notice, one of the license notices in the documentation
28 * and/or other materials provided with the distribution.
29 * 25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 * SOFTWARE.
30 */ 34 */
31 35
32#include <linux/completion.h> 36#include <linux/completion.h>
@@ -126,8 +130,7 @@ struct rdma_id_private {
126 130
127 struct completion comp; 131 struct completion comp;
128 atomic_t refcount; 132 atomic_t refcount;
129 wait_queue_head_t wait_remove; 133 struct mutex handler_mutex;
130 atomic_t dev_remove;
131 134
132 int backlog; 135 int backlog;
133 int timeout_ms; 136 int timeout_ms;
@@ -351,26 +354,15 @@ static void cma_deref_id(struct rdma_id_private *id_priv)
351 complete(&id_priv->comp); 354 complete(&id_priv->comp);
352} 355}
353 356
354static int cma_disable_remove(struct rdma_id_private *id_priv, 357static int cma_disable_callback(struct rdma_id_private *id_priv,
355 enum cma_state state) 358 enum cma_state state)
356{ 359{
357 unsigned long flags; 360 mutex_lock(&id_priv->handler_mutex);
358 int ret; 361 if (id_priv->state != state) {
359 362 mutex_unlock(&id_priv->handler_mutex);
360 spin_lock_irqsave(&id_priv->lock, flags); 363 return -EINVAL;
361 if (id_priv->state == state) { 364 }
362 atomic_inc(&id_priv->dev_remove); 365 return 0;
363 ret = 0;
364 } else
365 ret = -EINVAL;
366 spin_unlock_irqrestore(&id_priv->lock, flags);
367 return ret;
368}
369
370static void cma_enable_remove(struct rdma_id_private *id_priv)
371{
372 if (atomic_dec_and_test(&id_priv->dev_remove))
373 wake_up(&id_priv->wait_remove);
374} 366}
375 367
376static int cma_has_cm_dev(struct rdma_id_private *id_priv) 368static int cma_has_cm_dev(struct rdma_id_private *id_priv)
@@ -395,8 +387,7 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
395 mutex_init(&id_priv->qp_mutex); 387 mutex_init(&id_priv->qp_mutex);
396 init_completion(&id_priv->comp); 388 init_completion(&id_priv->comp);
397 atomic_set(&id_priv->refcount, 1); 389 atomic_set(&id_priv->refcount, 1);
398 init_waitqueue_head(&id_priv->wait_remove); 390 mutex_init(&id_priv->handler_mutex);
399 atomic_set(&id_priv->dev_remove, 0);
400 INIT_LIST_HEAD(&id_priv->listen_list); 391 INIT_LIST_HEAD(&id_priv->listen_list);
401 INIT_LIST_HEAD(&id_priv->mc_list); 392 INIT_LIST_HEAD(&id_priv->mc_list);
402 get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num); 393 get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
@@ -923,7 +914,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
923 struct rdma_cm_event event; 914 struct rdma_cm_event event;
924 int ret = 0; 915 int ret = 0;
925 916
926 if (cma_disable_remove(id_priv, CMA_CONNECT)) 917 if (cma_disable_callback(id_priv, CMA_CONNECT))
927 return 0; 918 return 0;
928 919
929 memset(&event, 0, sizeof event); 920 memset(&event, 0, sizeof event);
@@ -970,7 +961,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
970 event.param.conn.private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; 961 event.param.conn.private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
971 break; 962 break;
972 default: 963 default:
973 printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", 964 printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d\n",
974 ib_event->event); 965 ib_event->event);
975 goto out; 966 goto out;
976 } 967 }
@@ -980,12 +971,12 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
980 /* Destroy the CM ID by returning a non-zero value. */ 971 /* Destroy the CM ID by returning a non-zero value. */
981 id_priv->cm_id.ib = NULL; 972 id_priv->cm_id.ib = NULL;
982 cma_exch(id_priv, CMA_DESTROYING); 973 cma_exch(id_priv, CMA_DESTROYING);
983 cma_enable_remove(id_priv); 974 mutex_unlock(&id_priv->handler_mutex);
984 rdma_destroy_id(&id_priv->id); 975 rdma_destroy_id(&id_priv->id);
985 return ret; 976 return ret;
986 } 977 }
987out: 978out:
988 cma_enable_remove(id_priv); 979 mutex_unlock(&id_priv->handler_mutex);
989 return ret; 980 return ret;
990} 981}
991 982
@@ -998,6 +989,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
998 union cma_ip_addr *src, *dst; 989 union cma_ip_addr *src, *dst;
999 __be16 port; 990 __be16 port;
1000 u8 ip_ver; 991 u8 ip_ver;
992 int ret;
1001 993
1002 if (cma_get_net_info(ib_event->private_data, listen_id->ps, 994 if (cma_get_net_info(ib_event->private_data, listen_id->ps,
1003 &ip_ver, &port, &src, &dst)) 995 &ip_ver, &port, &src, &dst))
@@ -1022,10 +1014,11 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
1022 if (rt->num_paths == 2) 1014 if (rt->num_paths == 2)
1023 rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; 1015 rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
1024 1016
1025 ib_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
1026 ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); 1017 ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
1027 ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey)); 1018 ret = rdma_translate_ip(&id->route.addr.src_addr,
1028 rt->addr.dev_addr.dev_type = RDMA_NODE_IB_CA; 1019 &id->route.addr.dev_addr);
1020 if (ret)
1021 goto destroy_id;
1029 1022
1030 id_priv = container_of(id, struct rdma_id_private, id); 1023 id_priv = container_of(id, struct rdma_id_private, id);
1031 id_priv->state = CMA_CONNECT; 1024 id_priv->state = CMA_CONNECT;
@@ -1095,7 +1088,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
1095 int offset, ret; 1088 int offset, ret;
1096 1089
1097 listen_id = cm_id->context; 1090 listen_id = cm_id->context;
1098 if (cma_disable_remove(listen_id, CMA_LISTEN)) 1091 if (cma_disable_callback(listen_id, CMA_LISTEN))
1099 return -ECONNABORTED; 1092 return -ECONNABORTED;
1100 1093
1101 memset(&event, 0, sizeof event); 1094 memset(&event, 0, sizeof event);
@@ -1116,7 +1109,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
1116 goto out; 1109 goto out;
1117 } 1110 }
1118 1111
1119 atomic_inc(&conn_id->dev_remove); 1112 mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
1120 mutex_lock(&lock); 1113 mutex_lock(&lock);
1121 ret = cma_acquire_dev(conn_id); 1114 ret = cma_acquire_dev(conn_id);
1122 mutex_unlock(&lock); 1115 mutex_unlock(&lock);
@@ -1138,7 +1131,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
1138 !cma_is_ud_ps(conn_id->id.ps)) 1131 !cma_is_ud_ps(conn_id->id.ps))
1139 ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0); 1132 ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
1140 mutex_unlock(&lock); 1133 mutex_unlock(&lock);
1141 cma_enable_remove(conn_id); 1134 mutex_unlock(&conn_id->handler_mutex);
1142 goto out; 1135 goto out;
1143 } 1136 }
1144 1137
@@ -1147,11 +1140,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
1147 1140
1148release_conn_id: 1141release_conn_id:
1149 cma_exch(conn_id, CMA_DESTROYING); 1142 cma_exch(conn_id, CMA_DESTROYING);
1150 cma_enable_remove(conn_id); 1143 mutex_unlock(&conn_id->handler_mutex);
1151 rdma_destroy_id(&conn_id->id); 1144 rdma_destroy_id(&conn_id->id);
1152 1145
1153out: 1146out:
1154 cma_enable_remove(listen_id); 1147 mutex_unlock(&listen_id->handler_mutex);
1155 return ret; 1148 return ret;
1156} 1149}
1157 1150
@@ -1217,7 +1210,7 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
1217 struct sockaddr_in *sin; 1210 struct sockaddr_in *sin;
1218 int ret = 0; 1211 int ret = 0;
1219 1212
1220 if (cma_disable_remove(id_priv, CMA_CONNECT)) 1213 if (cma_disable_callback(id_priv, CMA_CONNECT))
1221 return 0; 1214 return 0;
1222 1215
1223 memset(&event, 0, sizeof event); 1216 memset(&event, 0, sizeof event);
@@ -1261,12 +1254,12 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
1261 /* Destroy the CM ID by returning a non-zero value. */ 1254 /* Destroy the CM ID by returning a non-zero value. */
1262 id_priv->cm_id.iw = NULL; 1255 id_priv->cm_id.iw = NULL;
1263 cma_exch(id_priv, CMA_DESTROYING); 1256 cma_exch(id_priv, CMA_DESTROYING);
1264 cma_enable_remove(id_priv); 1257 mutex_unlock(&id_priv->handler_mutex);
1265 rdma_destroy_id(&id_priv->id); 1258 rdma_destroy_id(&id_priv->id);
1266 return ret; 1259 return ret;
1267 } 1260 }
1268 1261
1269 cma_enable_remove(id_priv); 1262 mutex_unlock(&id_priv->handler_mutex);
1270 return ret; 1263 return ret;
1271} 1264}
1272 1265
@@ -1282,7 +1275,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
1282 struct ib_device_attr attr; 1275 struct ib_device_attr attr;
1283 1276
1284 listen_id = cm_id->context; 1277 listen_id = cm_id->context;
1285 if (cma_disable_remove(listen_id, CMA_LISTEN)) 1278 if (cma_disable_callback(listen_id, CMA_LISTEN))
1286 return -ECONNABORTED; 1279 return -ECONNABORTED;
1287 1280
1288 /* Create a new RDMA id for the new IW CM ID */ 1281 /* Create a new RDMA id for the new IW CM ID */
@@ -1294,19 +1287,19 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
1294 goto out; 1287 goto out;
1295 } 1288 }
1296 conn_id = container_of(new_cm_id, struct rdma_id_private, id); 1289 conn_id = container_of(new_cm_id, struct rdma_id_private, id);
1297 atomic_inc(&conn_id->dev_remove); 1290 mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
1298 conn_id->state = CMA_CONNECT; 1291 conn_id->state = CMA_CONNECT;
1299 1292
1300 dev = ip_dev_find(&init_net, iw_event->local_addr.sin_addr.s_addr); 1293 dev = ip_dev_find(&init_net, iw_event->local_addr.sin_addr.s_addr);
1301 if (!dev) { 1294 if (!dev) {
1302 ret = -EADDRNOTAVAIL; 1295 ret = -EADDRNOTAVAIL;
1303 cma_enable_remove(conn_id); 1296 mutex_unlock(&conn_id->handler_mutex);
1304 rdma_destroy_id(new_cm_id); 1297 rdma_destroy_id(new_cm_id);
1305 goto out; 1298 goto out;
1306 } 1299 }
1307 ret = rdma_copy_addr(&conn_id->id.route.addr.dev_addr, dev, NULL); 1300 ret = rdma_copy_addr(&conn_id->id.route.addr.dev_addr, dev, NULL);
1308 if (ret) { 1301 if (ret) {
1309 cma_enable_remove(conn_id); 1302 mutex_unlock(&conn_id->handler_mutex);
1310 rdma_destroy_id(new_cm_id); 1303 rdma_destroy_id(new_cm_id);
1311 goto out; 1304 goto out;
1312 } 1305 }
@@ -1315,7 +1308,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
1315 ret = cma_acquire_dev(conn_id); 1308 ret = cma_acquire_dev(conn_id);
1316 mutex_unlock(&lock); 1309 mutex_unlock(&lock);
1317 if (ret) { 1310 if (ret) {
1318 cma_enable_remove(conn_id); 1311 mutex_unlock(&conn_id->handler_mutex);
1319 rdma_destroy_id(new_cm_id); 1312 rdma_destroy_id(new_cm_id);
1320 goto out; 1313 goto out;
1321 } 1314 }
@@ -1331,7 +1324,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
1331 1324
1332 ret = ib_query_device(conn_id->id.device, &attr); 1325 ret = ib_query_device(conn_id->id.device, &attr);
1333 if (ret) { 1326 if (ret) {
1334 cma_enable_remove(conn_id); 1327 mutex_unlock(&conn_id->handler_mutex);
1335 rdma_destroy_id(new_cm_id); 1328 rdma_destroy_id(new_cm_id);
1336 goto out; 1329 goto out;
1337 } 1330 }
@@ -1347,14 +1340,17 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
1347 /* User wants to destroy the CM ID */ 1340 /* User wants to destroy the CM ID */
1348 conn_id->cm_id.iw = NULL; 1341 conn_id->cm_id.iw = NULL;
1349 cma_exch(conn_id, CMA_DESTROYING); 1342 cma_exch(conn_id, CMA_DESTROYING);
1350 cma_enable_remove(conn_id); 1343 mutex_unlock(&conn_id->handler_mutex);
1351 rdma_destroy_id(&conn_id->id); 1344 rdma_destroy_id(&conn_id->id);
1345 goto out;
1352 } 1346 }
1353 1347
1348 mutex_unlock(&conn_id->handler_mutex);
1349
1354out: 1350out:
1355 if (dev) 1351 if (dev)
1356 dev_put(dev); 1352 dev_put(dev);
1357 cma_enable_remove(listen_id); 1353 mutex_unlock(&listen_id->handler_mutex);
1358 return ret; 1354 return ret;
1359} 1355}
1360 1356
@@ -1446,7 +1442,7 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
1446 ret = rdma_listen(id, id_priv->backlog); 1442 ret = rdma_listen(id, id_priv->backlog);
1447 if (ret) 1443 if (ret)
1448 printk(KERN_WARNING "RDMA CMA: cma_listen_on_dev, error %d, " 1444 printk(KERN_WARNING "RDMA CMA: cma_listen_on_dev, error %d, "
1449 "listening on device %s", ret, cma_dev->device->name); 1445 "listening on device %s\n", ret, cma_dev->device->name);
1450} 1446}
1451 1447
1452static void cma_listen_on_all(struct rdma_id_private *id_priv) 1448static void cma_listen_on_all(struct rdma_id_private *id_priv)
@@ -1586,7 +1582,7 @@ static void cma_work_handler(struct work_struct *_work)
1586 struct rdma_id_private *id_priv = work->id; 1582 struct rdma_id_private *id_priv = work->id;
1587 int destroy = 0; 1583 int destroy = 0;
1588 1584
1589 atomic_inc(&id_priv->dev_remove); 1585 mutex_lock(&id_priv->handler_mutex);
1590 if (!cma_comp_exch(id_priv, work->old_state, work->new_state)) 1586 if (!cma_comp_exch(id_priv, work->old_state, work->new_state))
1591 goto out; 1587 goto out;
1592 1588
@@ -1595,7 +1591,7 @@ static void cma_work_handler(struct work_struct *_work)
1595 destroy = 1; 1591 destroy = 1;
1596 } 1592 }
1597out: 1593out:
1598 cma_enable_remove(id_priv); 1594 mutex_unlock(&id_priv->handler_mutex);
1599 cma_deref_id(id_priv); 1595 cma_deref_id(id_priv);
1600 if (destroy) 1596 if (destroy)
1601 rdma_destroy_id(&id_priv->id); 1597 rdma_destroy_id(&id_priv->id);
@@ -1758,7 +1754,7 @@ static void addr_handler(int status, struct sockaddr *src_addr,
1758 struct rdma_cm_event event; 1754 struct rdma_cm_event event;
1759 1755
1760 memset(&event, 0, sizeof event); 1756 memset(&event, 0, sizeof event);
1761 atomic_inc(&id_priv->dev_remove); 1757 mutex_lock(&id_priv->handler_mutex);
1762 1758
1763 /* 1759 /*
1764 * Grab mutex to block rdma_destroy_id() from removing the device while 1760 * Grab mutex to block rdma_destroy_id() from removing the device while
@@ -1787,13 +1783,13 @@ static void addr_handler(int status, struct sockaddr *src_addr,
1787 1783
1788 if (id_priv->id.event_handler(&id_priv->id, &event)) { 1784 if (id_priv->id.event_handler(&id_priv->id, &event)) {
1789 cma_exch(id_priv, CMA_DESTROYING); 1785 cma_exch(id_priv, CMA_DESTROYING);
1790 cma_enable_remove(id_priv); 1786 mutex_unlock(&id_priv->handler_mutex);
1791 cma_deref_id(id_priv); 1787 cma_deref_id(id_priv);
1792 rdma_destroy_id(&id_priv->id); 1788 rdma_destroy_id(&id_priv->id);
1793 return; 1789 return;
1794 } 1790 }
1795out: 1791out:
1796 cma_enable_remove(id_priv); 1792 mutex_unlock(&id_priv->handler_mutex);
1797 cma_deref_id(id_priv); 1793 cma_deref_id(id_priv);
1798} 1794}
1799 1795
@@ -2120,7 +2116,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
2120 struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd; 2116 struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;
2121 int ret = 0; 2117 int ret = 0;
2122 2118
2123 if (cma_disable_remove(id_priv, CMA_CONNECT)) 2119 if (cma_disable_callback(id_priv, CMA_CONNECT))
2124 return 0; 2120 return 0;
2125 2121
2126 memset(&event, 0, sizeof event); 2122 memset(&event, 0, sizeof event);
@@ -2151,7 +2147,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
2151 event.status = 0; 2147 event.status = 0;
2152 break; 2148 break;
2153 default: 2149 default:
2154 printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", 2150 printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d\n",
2155 ib_event->event); 2151 ib_event->event);
2156 goto out; 2152 goto out;
2157 } 2153 }
@@ -2161,12 +2157,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
2161 /* Destroy the CM ID by returning a non-zero value. */ 2157 /* Destroy the CM ID by returning a non-zero value. */
2162 id_priv->cm_id.ib = NULL; 2158 id_priv->cm_id.ib = NULL;
2163 cma_exch(id_priv, CMA_DESTROYING); 2159 cma_exch(id_priv, CMA_DESTROYING);
2164 cma_enable_remove(id_priv); 2160 mutex_unlock(&id_priv->handler_mutex);
2165 rdma_destroy_id(&id_priv->id); 2161 rdma_destroy_id(&id_priv->id);
2166 return ret; 2162 return ret;
2167 } 2163 }
2168out: 2164out:
2169 cma_enable_remove(id_priv); 2165 mutex_unlock(&id_priv->handler_mutex);
2170 return ret; 2166 return ret;
2171} 2167}
2172 2168
@@ -2564,8 +2560,8 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
2564 int ret; 2560 int ret;
2565 2561
2566 id_priv = mc->id_priv; 2562 id_priv = mc->id_priv;
2567 if (cma_disable_remove(id_priv, CMA_ADDR_BOUND) && 2563 if (cma_disable_callback(id_priv, CMA_ADDR_BOUND) &&
2568 cma_disable_remove(id_priv, CMA_ADDR_RESOLVED)) 2564 cma_disable_callback(id_priv, CMA_ADDR_RESOLVED))
2569 return 0; 2565 return 0;
2570 2566
2571 mutex_lock(&id_priv->qp_mutex); 2567 mutex_lock(&id_priv->qp_mutex);
@@ -2590,12 +2586,12 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
2590 ret = id_priv->id.event_handler(&id_priv->id, &event); 2586 ret = id_priv->id.event_handler(&id_priv->id, &event);
2591 if (ret) { 2587 if (ret) {
2592 cma_exch(id_priv, CMA_DESTROYING); 2588 cma_exch(id_priv, CMA_DESTROYING);
2593 cma_enable_remove(id_priv); 2589 mutex_unlock(&id_priv->handler_mutex);
2594 rdma_destroy_id(&id_priv->id); 2590 rdma_destroy_id(&id_priv->id);
2595 return 0; 2591 return 0;
2596 } 2592 }
2597 2593
2598 cma_enable_remove(id_priv); 2594 mutex_unlock(&id_priv->handler_mutex);
2599 return 0; 2595 return 0;
2600} 2596}
2601 2597
@@ -2754,6 +2750,7 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv)
2754{ 2750{
2755 struct rdma_cm_event event; 2751 struct rdma_cm_event event;
2756 enum cma_state state; 2752 enum cma_state state;
2753 int ret = 0;
2757 2754
2758 /* Record that we want to remove the device */ 2755 /* Record that we want to remove the device */
2759 state = cma_exch(id_priv, CMA_DEVICE_REMOVAL); 2756 state = cma_exch(id_priv, CMA_DEVICE_REMOVAL);
@@ -2761,15 +2758,18 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv)
2761 return 0; 2758 return 0;
2762 2759
2763 cma_cancel_operation(id_priv, state); 2760 cma_cancel_operation(id_priv, state);
2764 wait_event(id_priv->wait_remove, !atomic_read(&id_priv->dev_remove)); 2761 mutex_lock(&id_priv->handler_mutex);
2765 2762
2766 /* Check for destruction from another callback. */ 2763 /* Check for destruction from another callback. */
2767 if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL)) 2764 if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
2768 return 0; 2765 goto out;
2769 2766
2770 memset(&event, 0, sizeof event); 2767 memset(&event, 0, sizeof event);
2771 event.event = RDMA_CM_EVENT_DEVICE_REMOVAL; 2768 event.event = RDMA_CM_EVENT_DEVICE_REMOVAL;
2772 return id_priv->id.event_handler(&id_priv->id, &event); 2769 ret = id_priv->id.event_handler(&id_priv->id, &event);
2770out:
2771 mutex_unlock(&id_priv->handler_mutex);
2772 return ret;
2773} 2773}
2774 2774
2775static void cma_process_remove(struct cma_device *cma_dev) 2775static void cma_process_remove(struct cma_device *cma_dev)