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