@@ -146,28 +146,27 @@ static int copy_private_data(struct iw_cm_event *event)
146
146
return 0 ;
147
147
}
148
148
149
+ static void free_cm_id (struct iwcm_id_private * cm_id_priv )
150
+ {
151
+ dealloc_work_entries (cm_id_priv );
152
+ kfree (cm_id_priv );
153
+ }
154
+
149
155
/*
150
156
* Release a reference on cm_id. If the last reference is being
151
157
* released, enable the waiting thread (in iw_destroy_cm_id) to
152
158
* get woken up, and return 1 if a thread is already waiting.
153
159
*/
154
160
static int iwcm_deref_id (struct iwcm_id_private * cm_id_priv )
155
161
{
156
- int ret = 0 ;
157
-
158
162
BUG_ON (atomic_read (& cm_id_priv -> refcount )== 0 );
159
163
if (atomic_dec_and_test (& cm_id_priv -> refcount )) {
160
164
BUG_ON (!list_empty (& cm_id_priv -> work_list ));
161
- if (waitqueue_active (& cm_id_priv -> destroy_comp .wait )) {
162
- BUG_ON (cm_id_priv -> state != IW_CM_STATE_DESTROYING );
163
- BUG_ON (test_bit (IWCM_F_CALLBACK_DESTROY ,
164
- & cm_id_priv -> flags ));
165
- ret = 1 ;
166
- }
167
165
complete (& cm_id_priv -> destroy_comp );
166
+ return 1 ;
168
167
}
169
168
170
- return ret ;
169
+ return 0 ;
171
170
}
172
171
173
172
static void add_ref (struct iw_cm_id * cm_id )
@@ -181,7 +180,11 @@ static void rem_ref(struct iw_cm_id *cm_id)
181
180
{
182
181
struct iwcm_id_private * cm_id_priv ;
183
182
cm_id_priv = container_of (cm_id , struct iwcm_id_private , id );
184
- iwcm_deref_id (cm_id_priv );
183
+ if (iwcm_deref_id (cm_id_priv ) &&
184
+ test_bit (IWCM_F_CALLBACK_DESTROY , & cm_id_priv -> flags )) {
185
+ BUG_ON (!list_empty (& cm_id_priv -> work_list ));
186
+ free_cm_id (cm_id_priv );
187
+ }
185
188
}
186
189
187
190
static int cm_event_handler (struct iw_cm_id * cm_id , struct iw_cm_event * event );
@@ -355,7 +358,9 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
355
358
case IW_CM_STATE_CONN_RECV :
356
359
/*
357
360
* App called destroy before/without calling accept after
358
- * receiving connection request event notification.
361
+ * receiving connection request event notification or
362
+ * returned non zero from the event callback function.
363
+ * In either case, must tell the provider to reject.
359
364
*/
360
365
cm_id_priv -> state = IW_CM_STATE_DESTROYING ;
361
366
break ;
@@ -391,9 +396,7 @@ void iw_destroy_cm_id(struct iw_cm_id *cm_id)
391
396
392
397
wait_for_completion (& cm_id_priv -> destroy_comp );
393
398
394
- dealloc_work_entries (cm_id_priv );
395
-
396
- kfree (cm_id_priv );
399
+ free_cm_id (cm_id_priv );
397
400
}
398
401
EXPORT_SYMBOL (iw_destroy_cm_id );
399
402
@@ -647,10 +650,11 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
647
650
/* Call the client CM handler */
648
651
ret = cm_id -> cm_handler (cm_id , iw_event );
649
652
if (ret ) {
653
+ iw_cm_reject (cm_id , NULL , 0 );
650
654
set_bit (IWCM_F_CALLBACK_DESTROY , & cm_id_priv -> flags );
651
655
destroy_cm_id (cm_id );
652
656
if (atomic_read (& cm_id_priv -> refcount )== 0 )
653
- kfree ( cm_id );
657
+ free_cm_id ( cm_id_priv );
654
658
}
655
659
656
660
out :
@@ -854,13 +858,12 @@ static void cm_work_handler(struct work_struct *_work)
854
858
destroy_cm_id (& cm_id_priv -> id );
855
859
}
856
860
BUG_ON (atomic_read (& cm_id_priv -> refcount )== 0 );
857
- if (iwcm_deref_id (cm_id_priv ))
858
- return ;
859
-
860
- if (atomic_read (& cm_id_priv -> refcount )== 0 &&
861
- test_bit (IWCM_F_CALLBACK_DESTROY , & cm_id_priv -> flags )) {
862
- dealloc_work_entries (cm_id_priv );
863
- kfree (cm_id_priv );
861
+ if (iwcm_deref_id (cm_id_priv )) {
862
+ if (test_bit (IWCM_F_CALLBACK_DESTROY ,
863
+ & cm_id_priv -> flags )) {
864
+ BUG_ON (!list_empty (& cm_id_priv -> work_list ));
865
+ free_cm_id (cm_id_priv );
866
+ }
864
867
return ;
865
868
}
866
869
spin_lock_irqsave (& cm_id_priv -> lock , flags );
0 commit comments