diff options
author | Sean Hefty <sean.hefty@intel.com> | 2007-05-07 14:49:00 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2007-05-14 16:54:49 -0400 |
commit | 8aa08602bdd617a9cdd147f19076a8c8a70e03ef (patch) | |
tree | 29f2565b26d1e74fa5f1af8f168007286a479929 /drivers/infiniband/core | |
parent | 4e430dcb7b132a4076e533a9d69907acecbe71be (diff) |
RDMA/cma: Simplify device removal handling code
Add a new routine and rename another to encapsulate common code for
synchronizing with device removal.
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r-- | drivers/infiniband/core/cma.c | 89 |
1 files changed, 48 insertions, 41 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index fde92ce45153..d026764c7e9c 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -346,7 +346,23 @@ static void cma_deref_id(struct rdma_id_private *id_priv) | |||
346 | complete(&id_priv->comp); | 346 | complete(&id_priv->comp); |
347 | } | 347 | } |
348 | 348 | ||
349 | static void cma_release_remove(struct rdma_id_private *id_priv) | 349 | static int cma_disable_remove(struct rdma_id_private *id_priv, |
350 | enum cma_state state) | ||
351 | { | ||
352 | unsigned long flags; | ||
353 | int ret; | ||
354 | |||
355 | spin_lock_irqsave(&id_priv->lock, flags); | ||
356 | if (id_priv->state == state) { | ||
357 | atomic_inc(&id_priv->dev_remove); | ||
358 | ret = 0; | ||
359 | } else | ||
360 | ret = -EINVAL; | ||
361 | spin_unlock_irqrestore(&id_priv->lock, flags); | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static void cma_enable_remove(struct rdma_id_private *id_priv) | ||
350 | { | 366 | { |
351 | if (atomic_dec_and_test(&id_priv->dev_remove)) | 367 | if (atomic_dec_and_test(&id_priv->dev_remove)) |
352 | wake_up(&id_priv->wait_remove); | 368 | wake_up(&id_priv->wait_remove); |
@@ -884,9 +900,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
884 | struct rdma_cm_event event; | 900 | struct rdma_cm_event event; |
885 | int ret = 0; | 901 | int ret = 0; |
886 | 902 | ||
887 | atomic_inc(&id_priv->dev_remove); | 903 | if (cma_disable_remove(id_priv, CMA_CONNECT)) |
888 | if (!cma_comp(id_priv, CMA_CONNECT)) | 904 | return 0; |
889 | goto out; | ||
890 | 905 | ||
891 | memset(&event, 0, sizeof event); | 906 | memset(&event, 0, sizeof event); |
892 | switch (ib_event->event) { | 907 | switch (ib_event->event) { |
@@ -942,12 +957,12 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
942 | /* Destroy the CM ID by returning a non-zero value. */ | 957 | /* Destroy the CM ID by returning a non-zero value. */ |
943 | id_priv->cm_id.ib = NULL; | 958 | id_priv->cm_id.ib = NULL; |
944 | cma_exch(id_priv, CMA_DESTROYING); | 959 | cma_exch(id_priv, CMA_DESTROYING); |
945 | cma_release_remove(id_priv); | 960 | cma_enable_remove(id_priv); |
946 | rdma_destroy_id(&id_priv->id); | 961 | rdma_destroy_id(&id_priv->id); |
947 | return ret; | 962 | return ret; |
948 | } | 963 | } |
949 | out: | 964 | out: |
950 | cma_release_remove(id_priv); | 965 | cma_enable_remove(id_priv); |
951 | return ret; | 966 | return ret; |
952 | } | 967 | } |
953 | 968 | ||
@@ -1057,11 +1072,8 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
1057 | int offset, ret; | 1072 | int offset, ret; |
1058 | 1073 | ||
1059 | listen_id = cm_id->context; | 1074 | listen_id = cm_id->context; |
1060 | atomic_inc(&listen_id->dev_remove); | 1075 | if (cma_disable_remove(listen_id, CMA_LISTEN)) |
1061 | if (!cma_comp(listen_id, CMA_LISTEN)) { | 1076 | return -ECONNABORTED; |
1062 | ret = -ECONNABORTED; | ||
1063 | goto out; | ||
1064 | } | ||
1065 | 1077 | ||
1066 | memset(&event, 0, sizeof event); | 1078 | memset(&event, 0, sizeof event); |
1067 | offset = cma_user_data_offset(listen_id->id.ps); | 1079 | offset = cma_user_data_offset(listen_id->id.ps); |
@@ -1101,11 +1113,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
1101 | 1113 | ||
1102 | release_conn_id: | 1114 | release_conn_id: |
1103 | cma_exch(conn_id, CMA_DESTROYING); | 1115 | cma_exch(conn_id, CMA_DESTROYING); |
1104 | cma_release_remove(conn_id); | 1116 | cma_enable_remove(conn_id); |
1105 | rdma_destroy_id(&conn_id->id); | 1117 | rdma_destroy_id(&conn_id->id); |
1106 | 1118 | ||
1107 | out: | 1119 | out: |
1108 | cma_release_remove(listen_id); | 1120 | cma_enable_remove(listen_id); |
1109 | return ret; | 1121 | return ret; |
1110 | } | 1122 | } |
1111 | 1123 | ||
@@ -1214,12 +1226,12 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) | |||
1214 | /* Destroy the CM ID by returning a non-zero value. */ | 1226 | /* Destroy the CM ID by returning a non-zero value. */ |
1215 | id_priv->cm_id.iw = NULL; | 1227 | id_priv->cm_id.iw = NULL; |
1216 | cma_exch(id_priv, CMA_DESTROYING); | 1228 | cma_exch(id_priv, CMA_DESTROYING); |
1217 | cma_release_remove(id_priv); | 1229 | cma_enable_remove(id_priv); |
1218 | rdma_destroy_id(&id_priv->id); | 1230 | rdma_destroy_id(&id_priv->id); |
1219 | return ret; | 1231 | return ret; |
1220 | } | 1232 | } |
1221 | 1233 | ||
1222 | cma_release_remove(id_priv); | 1234 | cma_enable_remove(id_priv); |
1223 | return ret; | 1235 | return ret; |
1224 | } | 1236 | } |
1225 | 1237 | ||
@@ -1234,11 +1246,8 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, | |||
1234 | int ret; | 1246 | int ret; |
1235 | 1247 | ||
1236 | listen_id = cm_id->context; | 1248 | listen_id = cm_id->context; |
1237 | atomic_inc(&listen_id->dev_remove); | 1249 | if (cma_disable_remove(listen_id, CMA_LISTEN)) |
1238 | if (!cma_comp(listen_id, CMA_LISTEN)) { | 1250 | return -ECONNABORTED; |
1239 | ret = -ECONNABORTED; | ||
1240 | goto out; | ||
1241 | } | ||
1242 | 1251 | ||
1243 | /* Create a new RDMA id for the new IW CM ID */ | 1252 | /* Create a new RDMA id for the new IW CM ID */ |
1244 | new_cm_id = rdma_create_id(listen_id->id.event_handler, | 1253 | new_cm_id = rdma_create_id(listen_id->id.event_handler, |
@@ -1255,13 +1264,13 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, | |||
1255 | dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr); | 1264 | dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr); |
1256 | if (!dev) { | 1265 | if (!dev) { |
1257 | ret = -EADDRNOTAVAIL; | 1266 | ret = -EADDRNOTAVAIL; |
1258 | cma_release_remove(conn_id); | 1267 | cma_enable_remove(conn_id); |
1259 | rdma_destroy_id(new_cm_id); | 1268 | rdma_destroy_id(new_cm_id); |
1260 | goto out; | 1269 | goto out; |
1261 | } | 1270 | } |
1262 | ret = rdma_copy_addr(&conn_id->id.route.addr.dev_addr, dev, NULL); | 1271 | ret = rdma_copy_addr(&conn_id->id.route.addr.dev_addr, dev, NULL); |
1263 | if (ret) { | 1272 | if (ret) { |
1264 | cma_release_remove(conn_id); | 1273 | cma_enable_remove(conn_id); |
1265 | rdma_destroy_id(new_cm_id); | 1274 | rdma_destroy_id(new_cm_id); |
1266 | goto out; | 1275 | goto out; |
1267 | } | 1276 | } |
@@ -1270,7 +1279,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, | |||
1270 | ret = cma_acquire_dev(conn_id); | 1279 | ret = cma_acquire_dev(conn_id); |
1271 | mutex_unlock(&lock); | 1280 | mutex_unlock(&lock); |
1272 | if (ret) { | 1281 | if (ret) { |
1273 | cma_release_remove(conn_id); | 1282 | cma_enable_remove(conn_id); |
1274 | rdma_destroy_id(new_cm_id); | 1283 | rdma_destroy_id(new_cm_id); |
1275 | goto out; | 1284 | goto out; |
1276 | } | 1285 | } |
@@ -1293,14 +1302,14 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, | |||
1293 | /* User wants to destroy the CM ID */ | 1302 | /* User wants to destroy the CM ID */ |
1294 | conn_id->cm_id.iw = NULL; | 1303 | conn_id->cm_id.iw = NULL; |
1295 | cma_exch(conn_id, CMA_DESTROYING); | 1304 | cma_exch(conn_id, CMA_DESTROYING); |
1296 | cma_release_remove(conn_id); | 1305 | cma_enable_remove(conn_id); |
1297 | rdma_destroy_id(&conn_id->id); | 1306 | rdma_destroy_id(&conn_id->id); |
1298 | } | 1307 | } |
1299 | 1308 | ||
1300 | out: | 1309 | out: |
1301 | if (dev) | 1310 | if (dev) |
1302 | dev_put(dev); | 1311 | dev_put(dev); |
1303 | cma_release_remove(listen_id); | 1312 | cma_enable_remove(listen_id); |
1304 | return ret; | 1313 | return ret; |
1305 | } | 1314 | } |
1306 | 1315 | ||
@@ -1519,7 +1528,7 @@ static void cma_work_handler(struct work_struct *_work) | |||
1519 | destroy = 1; | 1528 | destroy = 1; |
1520 | } | 1529 | } |
1521 | out: | 1530 | out: |
1522 | cma_release_remove(id_priv); | 1531 | cma_enable_remove(id_priv); |
1523 | cma_deref_id(id_priv); | 1532 | cma_deref_id(id_priv); |
1524 | if (destroy) | 1533 | if (destroy) |
1525 | rdma_destroy_id(&id_priv->id); | 1534 | rdma_destroy_id(&id_priv->id); |
@@ -1711,13 +1720,13 @@ static void addr_handler(int status, struct sockaddr *src_addr, | |||
1711 | 1720 | ||
1712 | if (id_priv->id.event_handler(&id_priv->id, &event)) { | 1721 | if (id_priv->id.event_handler(&id_priv->id, &event)) { |
1713 | cma_exch(id_priv, CMA_DESTROYING); | 1722 | cma_exch(id_priv, CMA_DESTROYING); |
1714 | cma_release_remove(id_priv); | 1723 | cma_enable_remove(id_priv); |
1715 | cma_deref_id(id_priv); | 1724 | cma_deref_id(id_priv); |
1716 | rdma_destroy_id(&id_priv->id); | 1725 | rdma_destroy_id(&id_priv->id); |
1717 | return; | 1726 | return; |
1718 | } | 1727 | } |
1719 | out: | 1728 | out: |
1720 | cma_release_remove(id_priv); | 1729 | cma_enable_remove(id_priv); |
1721 | cma_deref_id(id_priv); | 1730 | cma_deref_id(id_priv); |
1722 | } | 1731 | } |
1723 | 1732 | ||
@@ -2042,11 +2051,10 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, | |||
2042 | struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd; | 2051 | struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd; |
2043 | int ret = 0; | 2052 | int ret = 0; |
2044 | 2053 | ||
2045 | memset(&event, 0, sizeof event); | 2054 | if (cma_disable_remove(id_priv, CMA_CONNECT)) |
2046 | atomic_inc(&id_priv->dev_remove); | 2055 | return 0; |
2047 | if (!cma_comp(id_priv, CMA_CONNECT)) | ||
2048 | goto out; | ||
2049 | 2056 | ||
2057 | memset(&event, 0, sizeof event); | ||
2050 | switch (ib_event->event) { | 2058 | switch (ib_event->event) { |
2051 | case IB_CM_SIDR_REQ_ERROR: | 2059 | case IB_CM_SIDR_REQ_ERROR: |
2052 | event.event = RDMA_CM_EVENT_UNREACHABLE; | 2060 | event.event = RDMA_CM_EVENT_UNREACHABLE; |
@@ -2084,12 +2092,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, | |||
2084 | /* Destroy the CM ID by returning a non-zero value. */ | 2092 | /* Destroy the CM ID by returning a non-zero value. */ |
2085 | id_priv->cm_id.ib = NULL; | 2093 | id_priv->cm_id.ib = NULL; |
2086 | cma_exch(id_priv, CMA_DESTROYING); | 2094 | cma_exch(id_priv, CMA_DESTROYING); |
2087 | cma_release_remove(id_priv); | 2095 | cma_enable_remove(id_priv); |
2088 | rdma_destroy_id(&id_priv->id); | 2096 | rdma_destroy_id(&id_priv->id); |
2089 | return ret; | 2097 | return ret; |
2090 | } | 2098 | } |
2091 | out: | 2099 | out: |
2092 | cma_release_remove(id_priv); | 2100 | cma_enable_remove(id_priv); |
2093 | return ret; | 2101 | return ret; |
2094 | } | 2102 | } |
2095 | 2103 | ||
@@ -2499,10 +2507,9 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) | |||
2499 | int ret; | 2507 | int ret; |
2500 | 2508 | ||
2501 | id_priv = mc->id_priv; | 2509 | id_priv = mc->id_priv; |
2502 | atomic_inc(&id_priv->dev_remove); | 2510 | if (cma_disable_remove(id_priv, CMA_ADDR_BOUND) && |
2503 | if (!cma_comp(id_priv, CMA_ADDR_BOUND) && | 2511 | cma_disable_remove(id_priv, CMA_ADDR_RESOLVED)) |
2504 | !cma_comp(id_priv, CMA_ADDR_RESOLVED)) | 2512 | return 0; |
2505 | goto out; | ||
2506 | 2513 | ||
2507 | if (!status && id_priv->id.qp) | 2514 | if (!status && id_priv->id.qp) |
2508 | status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid, | 2515 | status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid, |
@@ -2524,12 +2531,12 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) | |||
2524 | ret = id_priv->id.event_handler(&id_priv->id, &event); | 2531 | ret = id_priv->id.event_handler(&id_priv->id, &event); |
2525 | if (ret) { | 2532 | if (ret) { |
2526 | cma_exch(id_priv, CMA_DESTROYING); | 2533 | cma_exch(id_priv, CMA_DESTROYING); |
2527 | cma_release_remove(id_priv); | 2534 | cma_enable_remove(id_priv); |
2528 | rdma_destroy_id(&id_priv->id); | 2535 | rdma_destroy_id(&id_priv->id); |
2529 | return 0; | 2536 | return 0; |
2530 | } | 2537 | } |
2531 | out: | 2538 | |
2532 | cma_release_remove(id_priv); | 2539 | cma_enable_remove(id_priv); |
2533 | return 0; | 2540 | return 0; |
2534 | } | 2541 | } |
2535 | 2542 | ||