@@ -79,6 +79,27 @@ qedr_fill_sockaddr6(const struct qed_iwarp_cm_info *cm_info,
79
79
}
80
80
}
81
81
82
+ static void qedr_iw_free_qp (struct kref * ref )
83
+ {
84
+ struct qedr_qp * qp = container_of (ref , struct qedr_qp , refcnt );
85
+
86
+ kfree (qp );
87
+ }
88
+
89
+ static void
90
+ qedr_iw_free_ep (struct kref * ref )
91
+ {
92
+ struct qedr_iw_ep * ep = container_of (ref , struct qedr_iw_ep , refcnt );
93
+
94
+ if (ep -> qp )
95
+ kref_put (& ep -> qp -> refcnt , qedr_iw_free_qp );
96
+
97
+ if (ep -> cm_id )
98
+ ep -> cm_id -> rem_ref (ep -> cm_id );
99
+
100
+ kfree (ep );
101
+ }
102
+
82
103
static void
83
104
qedr_iw_mpa_request (void * context , struct qed_iwarp_cm_event_params * params )
84
105
{
@@ -93,6 +114,7 @@ qedr_iw_mpa_request(void *context, struct qed_iwarp_cm_event_params *params)
93
114
94
115
ep -> dev = dev ;
95
116
ep -> qed_context = params -> ep_context ;
117
+ kref_init (& ep -> refcnt );
96
118
97
119
memset (& event , 0 , sizeof (event ));
98
120
event .event = IW_CM_EVENT_CONNECT_REQUEST ;
@@ -141,12 +163,10 @@ qedr_iw_close_event(void *context, struct qed_iwarp_cm_event_params *params)
141
163
{
142
164
struct qedr_iw_ep * ep = (struct qedr_iw_ep * )context ;
143
165
144
- if (ep -> cm_id ) {
166
+ if (ep -> cm_id )
145
167
qedr_iw_issue_event (context , params , IW_CM_EVENT_CLOSE );
146
168
147
- ep -> cm_id -> rem_ref (ep -> cm_id );
148
- ep -> cm_id = NULL ;
149
- }
169
+ kref_put (& ep -> refcnt , qedr_iw_free_ep );
150
170
}
151
171
152
172
static void
@@ -186,11 +206,13 @@ static void qedr_iw_disconnect_worker(struct work_struct *work)
186
206
struct qedr_qp * qp = ep -> qp ;
187
207
struct iw_cm_event event ;
188
208
189
- if (qp -> destroyed ) {
190
- kfree (dwork );
191
- qedr_iw_qp_rem_ref (& qp -> ibqp );
192
- return ;
193
- }
209
+ /* The qp won't be released until we release the ep.
210
+ * the ep's refcnt was increased before calling this
211
+ * function, therefore it is safe to access qp
212
+ */
213
+ if (test_and_set_bit (QEDR_IWARP_CM_WAIT_FOR_DISCONNECT ,
214
+ & qp -> iwarp_cm_flags ))
215
+ goto out ;
194
216
195
217
memset (& event , 0 , sizeof (event ));
196
218
event .status = dwork -> status ;
@@ -204,7 +226,6 @@ static void qedr_iw_disconnect_worker(struct work_struct *work)
204
226
else
205
227
qp_params .new_state = QED_ROCE_QP_STATE_SQD ;
206
228
207
- kfree (dwork );
208
229
209
230
if (ep -> cm_id )
210
231
ep -> cm_id -> event_handler (ep -> cm_id , & event );
@@ -214,7 +235,10 @@ static void qedr_iw_disconnect_worker(struct work_struct *work)
214
235
215
236
dev -> ops -> rdma_modify_qp (dev -> rdma_ctx , qp -> qed_qp , & qp_params );
216
237
217
- qedr_iw_qp_rem_ref (& qp -> ibqp );
238
+ complete (& ep -> qp -> iwarp_cm_comp );
239
+ out :
240
+ kfree (dwork );
241
+ kref_put (& ep -> refcnt , qedr_iw_free_ep );
218
242
}
219
243
220
244
static void
@@ -224,13 +248,17 @@ qedr_iw_disconnect_event(void *context,
224
248
struct qedr_discon_work * work ;
225
249
struct qedr_iw_ep * ep = (struct qedr_iw_ep * )context ;
226
250
struct qedr_dev * dev = ep -> dev ;
227
- struct qedr_qp * qp = ep -> qp ;
228
251
229
252
work = kzalloc (sizeof (* work ), GFP_ATOMIC );
230
253
if (!work )
231
254
return ;
232
255
233
- qedr_iw_qp_add_ref (& qp -> ibqp );
256
+ /* We can't get a close event before disconnect, but since
257
+ * we're scheduling a work queue we need to make sure close
258
+ * won't delete the ep, so we increase the refcnt
259
+ */
260
+ kref_get (& ep -> refcnt );
261
+
234
262
work -> ep = ep ;
235
263
work -> event = params -> event ;
236
264
work -> status = params -> status ;
@@ -252,16 +280,30 @@ qedr_iw_passive_complete(void *context,
252
280
if ((params -> status == - ECONNREFUSED ) && (!ep -> qp )) {
253
281
DP_DEBUG (dev , QEDR_MSG_IWARP ,
254
282
"PASSIVE connection refused releasing ep...\n" );
255
- kfree ( ep );
283
+ kref_put ( & ep -> refcnt , qedr_iw_free_ep );
256
284
return ;
257
285
}
258
286
287
+ complete (& ep -> qp -> iwarp_cm_comp );
259
288
qedr_iw_issue_event (context , params , IW_CM_EVENT_ESTABLISHED );
260
289
261
290
if (params -> status < 0 )
262
291
qedr_iw_close_event (context , params );
263
292
}
264
293
294
+ static void
295
+ qedr_iw_active_complete (void * context ,
296
+ struct qed_iwarp_cm_event_params * params )
297
+ {
298
+ struct qedr_iw_ep * ep = (struct qedr_iw_ep * )context ;
299
+
300
+ complete (& ep -> qp -> iwarp_cm_comp );
301
+ qedr_iw_issue_event (context , params , IW_CM_EVENT_CONNECT_REPLY );
302
+
303
+ if (params -> status < 0 )
304
+ kref_put (& ep -> refcnt , qedr_iw_free_ep );
305
+ }
306
+
265
307
static int
266
308
qedr_iw_mpa_reply (void * context , struct qed_iwarp_cm_event_params * params )
267
309
{
@@ -288,27 +330,15 @@ qedr_iw_event_handler(void *context, struct qed_iwarp_cm_event_params *params)
288
330
qedr_iw_mpa_reply (context , params );
289
331
break ;
290
332
case QED_IWARP_EVENT_PASSIVE_COMPLETE :
291
- ep -> during_connect = 0 ;
292
333
qedr_iw_passive_complete (context , params );
293
334
break ;
294
-
295
335
case QED_IWARP_EVENT_ACTIVE_COMPLETE :
296
- ep -> during_connect = 0 ;
297
- qedr_iw_issue_event (context ,
298
- params ,
299
- IW_CM_EVENT_CONNECT_REPLY );
300
- if (params -> status < 0 ) {
301
- struct qedr_iw_ep * ep = (struct qedr_iw_ep * )context ;
302
-
303
- ep -> cm_id -> rem_ref (ep -> cm_id );
304
- ep -> cm_id = NULL ;
305
- }
336
+ qedr_iw_active_complete (context , params );
306
337
break ;
307
338
case QED_IWARP_EVENT_DISCONNECT :
308
339
qedr_iw_disconnect_event (context , params );
309
340
break ;
310
341
case QED_IWARP_EVENT_CLOSE :
311
- ep -> during_connect = 0 ;
312
342
qedr_iw_close_event (context , params );
313
343
break ;
314
344
case QED_IWARP_EVENT_RQ_EMPTY :
@@ -476,6 +506,19 @@ qedr_addr6_resolve(struct qedr_dev *dev,
476
506
return rc ;
477
507
}
478
508
509
+ struct qedr_qp * qedr_iw_load_qp (struct qedr_dev * dev , u32 qpn )
510
+ {
511
+ struct qedr_qp * qp ;
512
+
513
+ xa_lock (& dev -> qps );
514
+ qp = xa_load (& dev -> qps , qpn );
515
+ if (qp )
516
+ kref_get (& qp -> refcnt );
517
+ xa_unlock (& dev -> qps );
518
+
519
+ return qp ;
520
+ }
521
+
479
522
int qedr_iw_connect (struct iw_cm_id * cm_id , struct iw_cm_conn_param * conn_param )
480
523
{
481
524
struct qedr_dev * dev = get_qedr_dev (cm_id -> device );
@@ -491,10 +534,6 @@ int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
491
534
int rc = 0 ;
492
535
int i ;
493
536
494
- qp = xa_load (& dev -> qps , conn_param -> qpn );
495
- if (unlikely (!qp ))
496
- return - EINVAL ;
497
-
498
537
laddr = (struct sockaddr_in * )& cm_id -> m_local_addr ;
499
538
raddr = (struct sockaddr_in * )& cm_id -> m_remote_addr ;
500
539
laddr6 = (struct sockaddr_in6 * )& cm_id -> m_local_addr ;
@@ -516,8 +555,15 @@ int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
516
555
return - ENOMEM ;
517
556
518
557
ep -> dev = dev ;
558
+ kref_init (& ep -> refcnt );
559
+
560
+ qp = qedr_iw_load_qp (dev , conn_param -> qpn );
561
+ if (!qp ) {
562
+ rc = - EINVAL ;
563
+ goto err ;
564
+ }
565
+
519
566
ep -> qp = qp ;
520
- qp -> ep = ep ;
521
567
cm_id -> add_ref (cm_id );
522
568
ep -> cm_id = cm_id ;
523
569
@@ -580,16 +626,20 @@ int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
580
626
in_params .qp = qp -> qed_qp ;
581
627
memcpy (in_params .local_mac_addr , dev -> ndev -> dev_addr , ETH_ALEN );
582
628
583
- ep -> during_connect = 1 ;
629
+ if (test_and_set_bit (QEDR_IWARP_CM_WAIT_FOR_CONNECT ,
630
+ & qp -> iwarp_cm_flags ))
631
+ goto err ; /* QP already being destroyed */
632
+
584
633
rc = dev -> ops -> iwarp_connect (dev -> rdma_ctx , & in_params , & out_params );
585
- if (rc )
634
+ if (rc ) {
635
+ complete (& qp -> iwarp_cm_comp );
586
636
goto err ;
637
+ }
587
638
588
639
return rc ;
589
640
590
641
err :
591
- cm_id -> rem_ref (cm_id );
592
- kfree (ep );
642
+ kref_put (& ep -> refcnt , qedr_iw_free_ep );
593
643
return rc ;
594
644
}
595
645
@@ -677,18 +727,17 @@ int qedr_iw_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
677
727
struct qedr_dev * dev = ep -> dev ;
678
728
struct qedr_qp * qp ;
679
729
struct qed_iwarp_accept_in params ;
680
- int rc ;
730
+ int rc = 0 ;
681
731
682
732
DP_DEBUG (dev , QEDR_MSG_IWARP , "Accept on qpid=%d\n" , conn_param -> qpn );
683
733
684
- qp = xa_load ( & dev -> qps , conn_param -> qpn );
734
+ qp = qedr_iw_load_qp ( dev , conn_param -> qpn );
685
735
if (!qp ) {
686
736
DP_ERR (dev , "Invalid QP number %d\n" , conn_param -> qpn );
687
737
return - EINVAL ;
688
738
}
689
739
690
740
ep -> qp = qp ;
691
- qp -> ep = ep ;
692
741
cm_id -> add_ref (cm_id );
693
742
ep -> cm_id = cm_id ;
694
743
@@ -700,15 +749,21 @@ int qedr_iw_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
700
749
params .ird = conn_param -> ird ;
701
750
params .ord = conn_param -> ord ;
702
751
703
- ep -> during_connect = 1 ;
752
+ if (test_and_set_bit (QEDR_IWARP_CM_WAIT_FOR_CONNECT ,
753
+ & qp -> iwarp_cm_flags ))
754
+ goto err ; /* QP already destroyed */
755
+
704
756
rc = dev -> ops -> iwarp_accept (dev -> rdma_ctx , & params );
705
- if (rc )
757
+ if (rc ) {
758
+ complete (& qp -> iwarp_cm_comp );
706
759
goto err ;
760
+ }
707
761
708
762
return rc ;
763
+
709
764
err :
710
- ep -> during_connect = 0 ;
711
- cm_id -> rem_ref ( cm_id );
765
+ kref_put ( & ep -> refcnt , qedr_iw_free_ep ) ;
766
+
712
767
return rc ;
713
768
}
714
769
@@ -731,17 +786,14 @@ void qedr_iw_qp_add_ref(struct ib_qp *ibqp)
731
786
{
732
787
struct qedr_qp * qp = get_qedr_qp (ibqp );
733
788
734
- atomic_inc (& qp -> refcnt );
789
+ kref_get (& qp -> refcnt );
735
790
}
736
791
737
792
void qedr_iw_qp_rem_ref (struct ib_qp * ibqp )
738
793
{
739
794
struct qedr_qp * qp = get_qedr_qp (ibqp );
740
795
741
- if (atomic_dec_and_test (& qp -> refcnt )) {
742
- xa_erase (& qp -> dev -> qps , qp -> qp_id );
743
- kfree (qp );
744
- }
796
+ kref_put (& qp -> refcnt , qedr_iw_free_qp );
745
797
}
746
798
747
799
struct ib_qp * qedr_iw_get_qp (struct ib_device * ibdev , int qpn )
0 commit comments