@@ -130,8 +130,7 @@ struct rdma_id_private {
130130
131131 struct completion comp ;
132132 atomic_t refcount ;
133- wait_queue_head_t wait_remove ;
134- atomic_t dev_remove ;
133+ struct mutex handler_mutex ;
135134
136135 int backlog ;
137136 int timeout_ms ;
@@ -355,26 +354,15 @@ static void cma_deref_id(struct rdma_id_private *id_priv)
355354 complete (& id_priv -> comp );
356355}
357356
358- static int cma_disable_remove (struct rdma_id_private * id_priv ,
357+ static int cma_disable_callback (struct rdma_id_private * id_priv ,
359358 enum cma_state state )
360359{
361- unsigned long flags ;
362- int ret ;
363-
364- spin_lock_irqsave (& id_priv -> lock , flags );
365- if (id_priv -> state == state ) {
366- atomic_inc (& id_priv -> dev_remove );
367- ret = 0 ;
368- } else
369- ret = - EINVAL ;
370- spin_unlock_irqrestore (& id_priv -> lock , flags );
371- return ret ;
372- }
373-
374- static void cma_enable_remove (struct rdma_id_private * id_priv )
375- {
376- if (atomic_dec_and_test (& id_priv -> dev_remove ))
377- wake_up (& id_priv -> wait_remove );
360+ mutex_lock (& id_priv -> handler_mutex );
361+ if (id_priv -> state != state ) {
362+ mutex_unlock (& id_priv -> handler_mutex );
363+ return - EINVAL ;
364+ }
365+ return 0 ;
378366}
379367
380368static int cma_has_cm_dev (struct rdma_id_private * id_priv )
@@ -399,8 +387,7 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
399387 mutex_init (& id_priv -> qp_mutex );
400388 init_completion (& id_priv -> comp );
401389 atomic_set (& id_priv -> refcount , 1 );
402- init_waitqueue_head (& id_priv -> wait_remove );
403- atomic_set (& id_priv -> dev_remove , 0 );
390+ mutex_init (& id_priv -> handler_mutex );
404391 INIT_LIST_HEAD (& id_priv -> listen_list );
405392 INIT_LIST_HEAD (& id_priv -> mc_list );
406393 get_random_bytes (& id_priv -> seq_num , sizeof id_priv -> seq_num );
@@ -927,7 +914,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
927914 struct rdma_cm_event event ;
928915 int ret = 0 ;
929916
930- if (cma_disable_remove (id_priv , CMA_CONNECT ))
917+ if (cma_disable_callback (id_priv , CMA_CONNECT ))
931918 return 0 ;
932919
933920 memset (& event , 0 , sizeof event );
@@ -984,12 +971,12 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
984971 /* Destroy the CM ID by returning a non-zero value. */
985972 id_priv -> cm_id .ib = NULL ;
986973 cma_exch (id_priv , CMA_DESTROYING );
987- cma_enable_remove ( id_priv );
974+ mutex_unlock ( & id_priv -> handler_mutex );
988975 rdma_destroy_id (& id_priv -> id );
989976 return ret ;
990977 }
991978out :
992- cma_enable_remove ( id_priv );
979+ mutex_unlock ( & id_priv -> handler_mutex );
993980 return ret ;
994981}
995982
@@ -1101,7 +1088,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
11011088 int offset , ret ;
11021089
11031090 listen_id = cm_id -> context ;
1104- if (cma_disable_remove (listen_id , CMA_LISTEN ))
1091+ if (cma_disable_callback (listen_id , CMA_LISTEN ))
11051092 return - ECONNABORTED ;
11061093
11071094 memset (& event , 0 , sizeof event );
@@ -1122,7 +1109,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
11221109 goto out ;
11231110 }
11241111
1125- atomic_inc (& conn_id -> dev_remove );
1112+ mutex_lock_nested (& conn_id -> handler_mutex , SINGLE_DEPTH_NESTING );
11261113 mutex_lock (& lock );
11271114 ret = cma_acquire_dev (conn_id );
11281115 mutex_unlock (& lock );
@@ -1144,7 +1131,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
11441131 !cma_is_ud_ps (conn_id -> id .ps ))
11451132 ib_send_cm_mra (cm_id , CMA_CM_MRA_SETTING , NULL , 0 );
11461133 mutex_unlock (& lock );
1147- cma_enable_remove ( conn_id );
1134+ mutex_unlock ( & conn_id -> handler_mutex );
11481135 goto out ;
11491136 }
11501137
@@ -1153,11 +1140,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
11531140
11541141release_conn_id :
11551142 cma_exch (conn_id , CMA_DESTROYING );
1156- cma_enable_remove ( conn_id );
1143+ mutex_unlock ( & conn_id -> handler_mutex );
11571144 rdma_destroy_id (& conn_id -> id );
11581145
11591146out :
1160- cma_enable_remove ( listen_id );
1147+ mutex_unlock ( & listen_id -> handler_mutex );
11611148 return ret ;
11621149}
11631150
@@ -1223,7 +1210,7 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
12231210 struct sockaddr_in * sin ;
12241211 int ret = 0 ;
12251212
1226- if (cma_disable_remove (id_priv , CMA_CONNECT ))
1213+ if (cma_disable_callback (id_priv , CMA_CONNECT ))
12271214 return 0 ;
12281215
12291216 memset (& event , 0 , sizeof event );
@@ -1267,12 +1254,12 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
12671254 /* Destroy the CM ID by returning a non-zero value. */
12681255 id_priv -> cm_id .iw = NULL ;
12691256 cma_exch (id_priv , CMA_DESTROYING );
1270- cma_enable_remove ( id_priv );
1257+ mutex_unlock ( & id_priv -> handler_mutex );
12711258 rdma_destroy_id (& id_priv -> id );
12721259 return ret ;
12731260 }
12741261
1275- cma_enable_remove ( id_priv );
1262+ mutex_unlock ( & id_priv -> handler_mutex );
12761263 return ret ;
12771264}
12781265
@@ -1288,7 +1275,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
12881275 struct ib_device_attr attr ;
12891276
12901277 listen_id = cm_id -> context ;
1291- if (cma_disable_remove (listen_id , CMA_LISTEN ))
1278+ if (cma_disable_callback (listen_id , CMA_LISTEN ))
12921279 return - ECONNABORTED ;
12931280
12941281 /* Create a new RDMA id for the new IW CM ID */
@@ -1300,19 +1287,19 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
13001287 goto out ;
13011288 }
13021289 conn_id = container_of (new_cm_id , struct rdma_id_private , id );
1303- atomic_inc (& conn_id -> dev_remove );
1290+ mutex_lock_nested (& conn_id -> handler_mutex , SINGLE_DEPTH_NESTING );
13041291 conn_id -> state = CMA_CONNECT ;
13051292
13061293 dev = ip_dev_find (& init_net , iw_event -> local_addr .sin_addr .s_addr );
13071294 if (!dev ) {
13081295 ret = - EADDRNOTAVAIL ;
1309- cma_enable_remove ( conn_id );
1296+ mutex_unlock ( & conn_id -> handler_mutex );
13101297 rdma_destroy_id (new_cm_id );
13111298 goto out ;
13121299 }
13131300 ret = rdma_copy_addr (& conn_id -> id .route .addr .dev_addr , dev , NULL );
13141301 if (ret ) {
1315- cma_enable_remove ( conn_id );
1302+ mutex_unlock ( & conn_id -> handler_mutex );
13161303 rdma_destroy_id (new_cm_id );
13171304 goto out ;
13181305 }
@@ -1321,7 +1308,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
13211308 ret = cma_acquire_dev (conn_id );
13221309 mutex_unlock (& lock );
13231310 if (ret ) {
1324- cma_enable_remove ( conn_id );
1311+ mutex_unlock ( & conn_id -> handler_mutex );
13251312 rdma_destroy_id (new_cm_id );
13261313 goto out ;
13271314 }
@@ -1337,7 +1324,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
13371324
13381325 ret = ib_query_device (conn_id -> id .device , & attr );
13391326 if (ret ) {
1340- cma_enable_remove ( conn_id );
1327+ mutex_unlock ( & conn_id -> handler_mutex );
13411328 rdma_destroy_id (new_cm_id );
13421329 goto out ;
13431330 }
@@ -1353,14 +1340,17 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
13531340 /* User wants to destroy the CM ID */
13541341 conn_id -> cm_id .iw = NULL ;
13551342 cma_exch (conn_id , CMA_DESTROYING );
1356- cma_enable_remove ( conn_id );
1343+ mutex_unlock ( & conn_id -> handler_mutex );
13571344 rdma_destroy_id (& conn_id -> id );
1345+ goto out ;
13581346 }
13591347
1348+ mutex_unlock (& conn_id -> handler_mutex );
1349+
13601350out :
13611351 if (dev )
13621352 dev_put (dev );
1363- cma_enable_remove ( listen_id );
1353+ mutex_unlock ( & listen_id -> handler_mutex );
13641354 return ret ;
13651355}
13661356
@@ -1592,7 +1582,7 @@ static void cma_work_handler(struct work_struct *_work)
15921582 struct rdma_id_private * id_priv = work -> id ;
15931583 int destroy = 0 ;
15941584
1595- atomic_inc (& id_priv -> dev_remove );
1585+ mutex_lock (& id_priv -> handler_mutex );
15961586 if (!cma_comp_exch (id_priv , work -> old_state , work -> new_state ))
15971587 goto out ;
15981588
@@ -1601,7 +1591,7 @@ static void cma_work_handler(struct work_struct *_work)
16011591 destroy = 1 ;
16021592 }
16031593out :
1604- cma_enable_remove ( id_priv );
1594+ mutex_unlock ( & id_priv -> handler_mutex );
16051595 cma_deref_id (id_priv );
16061596 if (destroy )
16071597 rdma_destroy_id (& id_priv -> id );
@@ -1764,7 +1754,7 @@ static void addr_handler(int status, struct sockaddr *src_addr,
17641754 struct rdma_cm_event event ;
17651755
17661756 memset (& event , 0 , sizeof event );
1767- atomic_inc (& id_priv -> dev_remove );
1757+ mutex_lock (& id_priv -> handler_mutex );
17681758
17691759 /*
17701760 * Grab mutex to block rdma_destroy_id() from removing the device while
@@ -1793,13 +1783,13 @@ static void addr_handler(int status, struct sockaddr *src_addr,
17931783
17941784 if (id_priv -> id .event_handler (& id_priv -> id , & event )) {
17951785 cma_exch (id_priv , CMA_DESTROYING );
1796- cma_enable_remove ( id_priv );
1786+ mutex_unlock ( & id_priv -> handler_mutex );
17971787 cma_deref_id (id_priv );
17981788 rdma_destroy_id (& id_priv -> id );
17991789 return ;
18001790 }
18011791out :
1802- cma_enable_remove ( id_priv );
1792+ mutex_unlock ( & id_priv -> handler_mutex );
18031793 cma_deref_id (id_priv );
18041794}
18051795
@@ -2126,7 +2116,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
21262116 struct ib_cm_sidr_rep_event_param * rep = & ib_event -> param .sidr_rep_rcvd ;
21272117 int ret = 0 ;
21282118
2129- if (cma_disable_remove (id_priv , CMA_CONNECT ))
2119+ if (cma_disable_callback (id_priv , CMA_CONNECT ))
21302120 return 0 ;
21312121
21322122 memset (& event , 0 , sizeof event );
@@ -2167,12 +2157,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
21672157 /* Destroy the CM ID by returning a non-zero value. */
21682158 id_priv -> cm_id .ib = NULL ;
21692159 cma_exch (id_priv , CMA_DESTROYING );
2170- cma_enable_remove ( id_priv );
2160+ mutex_unlock ( & id_priv -> handler_mutex );
21712161 rdma_destroy_id (& id_priv -> id );
21722162 return ret ;
21732163 }
21742164out :
2175- cma_enable_remove ( id_priv );
2165+ mutex_unlock ( & id_priv -> handler_mutex );
21762166 return ret ;
21772167}
21782168
@@ -2570,8 +2560,8 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
25702560 int ret ;
25712561
25722562 id_priv = mc -> id_priv ;
2573- if (cma_disable_remove (id_priv , CMA_ADDR_BOUND ) &&
2574- cma_disable_remove (id_priv , CMA_ADDR_RESOLVED ))
2563+ if (cma_disable_callback (id_priv , CMA_ADDR_BOUND ) &&
2564+ cma_disable_callback (id_priv , CMA_ADDR_RESOLVED ))
25752565 return 0 ;
25762566
25772567 mutex_lock (& id_priv -> qp_mutex );
@@ -2596,12 +2586,12 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
25962586 ret = id_priv -> id .event_handler (& id_priv -> id , & event );
25972587 if (ret ) {
25982588 cma_exch (id_priv , CMA_DESTROYING );
2599- cma_enable_remove ( id_priv );
2589+ mutex_unlock ( & id_priv -> handler_mutex );
26002590 rdma_destroy_id (& id_priv -> id );
26012591 return 0 ;
26022592 }
26032593
2604- cma_enable_remove ( id_priv );
2594+ mutex_unlock ( & id_priv -> handler_mutex );
26052595 return 0 ;
26062596}
26072597
@@ -2760,22 +2750,26 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv)
27602750{
27612751 struct rdma_cm_event event ;
27622752 enum cma_state state ;
2753+ int ret = 0 ;
27632754
27642755 /* Record that we want to remove the device */
27652756 state = cma_exch (id_priv , CMA_DEVICE_REMOVAL );
27662757 if (state == CMA_DESTROYING )
27672758 return 0 ;
27682759
27692760 cma_cancel_operation (id_priv , state );
2770- wait_event ( id_priv -> wait_remove , ! atomic_read ( & id_priv -> dev_remove ) );
2761+ mutex_lock ( & id_priv -> handler_mutex );
27712762
27722763 /* Check for destruction from another callback. */
27732764 if (!cma_comp (id_priv , CMA_DEVICE_REMOVAL ))
2774- return 0 ;
2765+ goto out ;
27752766
27762767 memset (& event , 0 , sizeof event );
27772768 event .event = RDMA_CM_EVENT_DEVICE_REMOVAL ;
2778- return id_priv -> id .event_handler (& id_priv -> id , & event );
2769+ ret = id_priv -> id .event_handler (& id_priv -> id , & event );
2770+ out :
2771+ mutex_unlock (& id_priv -> handler_mutex );
2772+ return ret ;
27792773}
27802774
27812775static void cma_process_remove (struct cma_device * cma_dev )
0 commit comments