@@ -142,96 +142,115 @@ rpcrdma_cq_async_error_upcall(struct ib_event *event, void *context)
142
142
}
143
143
}
144
144
145
- static inline
146
- void rpcrdma_event_process (struct ib_wc * wc )
145
+ static void
146
+ rpcrdma_sendcq_process_wc (struct ib_wc * wc )
147
147
{
148
- struct rpcrdma_mw * frmr ;
149
- struct rpcrdma_rep * rep =
150
- (struct rpcrdma_rep * )(unsigned long ) wc -> wr_id ;
148
+ struct rpcrdma_mw * frmr = (struct rpcrdma_mw * )(unsigned long )wc -> wr_id ;
151
149
152
- dprintk ("RPC: %s: event rep %p status %X opcode %X length %u \n" ,
153
- __func__ , rep , wc -> status , wc -> opcode , wc -> byte_len );
150
+ dprintk ("RPC: %s: frmr %p status %X opcode %d \n" ,
151
+ __func__ , frmr , wc -> status , wc -> opcode );
154
152
155
- if (! rep ) /* send completion that we don't care about */
153
+ if (wc -> wr_id == 0ULL )
156
154
return ;
157
-
158
- if (IB_WC_SUCCESS != wc -> status ) {
159
- dprintk ("RPC: %s: WC opcode %d status %X, connection lost\n" ,
160
- __func__ , wc -> opcode , wc -> status );
161
- rep -> rr_len = ~0U ;
162
- if (wc -> opcode != IB_WC_FAST_REG_MR && wc -> opcode != IB_WC_LOCAL_INV )
163
- rpcrdma_schedule_tasklet (rep );
155
+ if (wc -> status != IB_WC_SUCCESS )
164
156
return ;
165
- }
166
157
167
- switch (wc -> opcode ) {
168
- case IB_WC_FAST_REG_MR :
169
- frmr = (struct rpcrdma_mw * )(unsigned long )wc -> wr_id ;
158
+ if (wc -> opcode == IB_WC_FAST_REG_MR )
170
159
frmr -> r .frmr .state = FRMR_IS_VALID ;
171
- break ;
172
- case IB_WC_LOCAL_INV :
173
- frmr = (struct rpcrdma_mw * )(unsigned long )wc -> wr_id ;
160
+ else if (wc -> opcode == IB_WC_LOCAL_INV )
174
161
frmr -> r .frmr .state = FRMR_IS_INVALID ;
175
- break ;
176
- case IB_WC_RECV :
177
- rep -> rr_len = wc -> byte_len ;
178
- ib_dma_sync_single_for_cpu (
179
- rdmab_to_ia (rep -> rr_buffer )-> ri_id -> device ,
180
- rep -> rr_iov .addr , rep -> rr_len , DMA_FROM_DEVICE );
181
- /* Keep (only) the most recent credits, after check validity */
182
- if (rep -> rr_len >= 16 ) {
183
- struct rpcrdma_msg * p =
184
- (struct rpcrdma_msg * ) rep -> rr_base ;
185
- unsigned int credits = ntohl (p -> rm_credit );
186
- if (credits == 0 ) {
187
- dprintk ("RPC: %s: server"
188
- " dropped credits to 0!\n" , __func__ );
189
- /* don't deadlock */
190
- credits = 1 ;
191
- } else if (credits > rep -> rr_buffer -> rb_max_requests ) {
192
- dprintk ("RPC: %s: server"
193
- " over-crediting: %d (%d)\n" ,
194
- __func__ , credits ,
195
- rep -> rr_buffer -> rb_max_requests );
196
- credits = rep -> rr_buffer -> rb_max_requests ;
197
- }
198
- atomic_set (& rep -> rr_buffer -> rb_credits , credits );
199
- }
200
- rpcrdma_schedule_tasklet (rep );
201
- break ;
202
- default :
203
- dprintk ("RPC: %s: unexpected WC event %X\n" ,
204
- __func__ , wc -> opcode );
205
- break ;
206
- }
207
162
}
208
163
209
- static inline int
210
- rpcrdma_cq_poll (struct ib_cq * cq )
164
+ static int
165
+ rpcrdma_sendcq_poll (struct ib_cq * cq )
211
166
{
212
167
struct ib_wc wc ;
213
168
int rc ;
214
169
215
- for (;;) {
216
- rc = ib_poll_cq (cq , 1 , & wc );
217
- if (rc < 0 ) {
218
- dprintk ("RPC: %s: ib_poll_cq failed %i\n" ,
219
- __func__ , rc );
220
- return rc ;
221
- }
222
- if (rc == 0 )
223
- break ;
170
+ while ((rc = ib_poll_cq (cq , 1 , & wc )) == 1 )
171
+ rpcrdma_sendcq_process_wc (& wc );
172
+ return rc ;
173
+ }
224
174
225
- rpcrdma_event_process (& wc );
175
+ /*
176
+ * Handle send, fast_reg_mr, and local_inv completions.
177
+ *
178
+ * Send events are typically suppressed and thus do not result
179
+ * in an upcall. Occasionally one is signaled, however. This
180
+ * prevents the provider's completion queue from wrapping and
181
+ * losing a completion.
182
+ */
183
+ static void
184
+ rpcrdma_sendcq_upcall (struct ib_cq * cq , void * cq_context )
185
+ {
186
+ int rc ;
187
+
188
+ rc = rpcrdma_sendcq_poll (cq );
189
+ if (rc ) {
190
+ dprintk ("RPC: %s: ib_poll_cq failed: %i\n" ,
191
+ __func__ , rc );
192
+ return ;
226
193
}
227
194
228
- return 0 ;
195
+ rc = ib_req_notify_cq (cq , IB_CQ_NEXT_COMP );
196
+ if (rc ) {
197
+ dprintk ("RPC: %s: ib_req_notify_cq failed: %i\n" ,
198
+ __func__ , rc );
199
+ return ;
200
+ }
201
+
202
+ rpcrdma_sendcq_poll (cq );
203
+ }
204
+
205
+ static void
206
+ rpcrdma_recvcq_process_wc (struct ib_wc * wc )
207
+ {
208
+ struct rpcrdma_rep * rep =
209
+ (struct rpcrdma_rep * )(unsigned long )wc -> wr_id ;
210
+
211
+ dprintk ("RPC: %s: rep %p status %X opcode %X length %u\n" ,
212
+ __func__ , rep , wc -> status , wc -> opcode , wc -> byte_len );
213
+
214
+ if (wc -> status != IB_WC_SUCCESS ) {
215
+ rep -> rr_len = ~0U ;
216
+ goto out_schedule ;
217
+ }
218
+ if (wc -> opcode != IB_WC_RECV )
219
+ return ;
220
+
221
+ rep -> rr_len = wc -> byte_len ;
222
+ ib_dma_sync_single_for_cpu (rdmab_to_ia (rep -> rr_buffer )-> ri_id -> device ,
223
+ rep -> rr_iov .addr , rep -> rr_len , DMA_FROM_DEVICE );
224
+
225
+ if (rep -> rr_len >= 16 ) {
226
+ struct rpcrdma_msg * p = (struct rpcrdma_msg * )rep -> rr_base ;
227
+ unsigned int credits = ntohl (p -> rm_credit );
228
+
229
+ if (credits == 0 )
230
+ credits = 1 ; /* don't deadlock */
231
+ else if (credits > rep -> rr_buffer -> rb_max_requests )
232
+ credits = rep -> rr_buffer -> rb_max_requests ;
233
+ atomic_set (& rep -> rr_buffer -> rb_credits , credits );
234
+ }
235
+
236
+ out_schedule :
237
+ rpcrdma_schedule_tasklet (rep );
238
+ }
239
+
240
+ static int
241
+ rpcrdma_recvcq_poll (struct ib_cq * cq )
242
+ {
243
+ struct ib_wc wc ;
244
+ int rc ;
245
+
246
+ while ((rc = ib_poll_cq (cq , 1 , & wc )) == 1 )
247
+ rpcrdma_recvcq_process_wc (& wc );
248
+ return rc ;
229
249
}
230
250
231
251
/*
232
- * rpcrdma_cq_event_upcall
252
+ * Handle receive completions.
233
253
*
234
- * This upcall handles recv and send events.
235
254
* It is reentrant but processes single events in order to maintain
236
255
* ordering of receives to keep server credits.
237
256
*
@@ -240,26 +259,27 @@ rpcrdma_cq_poll(struct ib_cq *cq)
240
259
* connection shutdown. That is, the structures required for
241
260
* the completion of the reply handler must remain intact until
242
261
* all memory has been reclaimed.
243
- *
244
- * Note that send events are suppressed and do not result in an upcall.
245
262
*/
246
263
static void
247
- rpcrdma_cq_event_upcall (struct ib_cq * cq , void * context )
264
+ rpcrdma_recvcq_upcall (struct ib_cq * cq , void * cq_context )
248
265
{
249
266
int rc ;
250
267
251
- rc = rpcrdma_cq_poll (cq );
252
- if (rc )
268
+ rc = rpcrdma_recvcq_poll (cq );
269
+ if (rc ) {
270
+ dprintk ("RPC: %s: ib_poll_cq failed: %i\n" ,
271
+ __func__ , rc );
253
272
return ;
273
+ }
254
274
255
275
rc = ib_req_notify_cq (cq , IB_CQ_NEXT_COMP );
256
276
if (rc ) {
257
- dprintk ("RPC: %s: ib_req_notify_cq failed %i\n" ,
277
+ dprintk ("RPC: %s: ib_req_notify_cq failed: %i\n" ,
258
278
__func__ , rc );
259
279
return ;
260
280
}
261
281
262
- rpcrdma_cq_poll (cq );
282
+ rpcrdma_recvcq_poll (cq );
263
283
}
264
284
265
285
#ifdef RPC_DEBUG
@@ -610,6 +630,7 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
610
630
struct rpcrdma_create_data_internal * cdata )
611
631
{
612
632
struct ib_device_attr devattr ;
633
+ struct ib_cq * sendcq , * recvcq ;
613
634
int rc , err ;
614
635
615
636
rc = ib_query_device (ia -> ri_id -> device , & devattr );
@@ -685,34 +706,51 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
685
706
ep -> rep_attr .cap .max_recv_sge );
686
707
687
708
/* set trigger for requesting send completion */
688
- ep -> rep_cqinit = ep -> rep_attr .cap .max_send_wr /2 /* - 1*/ ;
709
+ ep -> rep_cqinit = ep -> rep_attr .cap .max_send_wr /2 - 1 ;
689
710
if (ep -> rep_cqinit <= 2 )
690
711
ep -> rep_cqinit = 0 ;
691
712
INIT_CQCOUNT (ep );
692
713
ep -> rep_ia = ia ;
693
714
init_waitqueue_head (& ep -> rep_connect_wait );
694
715
INIT_DELAYED_WORK (& ep -> rep_connect_worker , rpcrdma_connect_worker );
695
716
696
- ep -> rep_cq = ib_create_cq (ia -> ri_id -> device , rpcrdma_cq_event_upcall ,
717
+ sendcq = ib_create_cq (ia -> ri_id -> device , rpcrdma_sendcq_upcall ,
697
718
rpcrdma_cq_async_error_upcall , NULL ,
698
- ep -> rep_attr .cap .max_recv_wr +
699
719
ep -> rep_attr .cap .max_send_wr + 1 , 0 );
700
- if (IS_ERR (ep -> rep_cq )) {
701
- rc = PTR_ERR (ep -> rep_cq );
702
- dprintk ("RPC: %s: ib_create_cq failed: %i\n" ,
720
+ if (IS_ERR (sendcq )) {
721
+ rc = PTR_ERR (sendcq );
722
+ dprintk ("RPC: %s: failed to create send CQ : %i\n" ,
703
723
__func__ , rc );
704
724
goto out1 ;
705
725
}
706
726
707
- rc = ib_req_notify_cq (ep -> rep_cq , IB_CQ_NEXT_COMP );
727
+ rc = ib_req_notify_cq (sendcq , IB_CQ_NEXT_COMP );
708
728
if (rc ) {
709
729
dprintk ("RPC: %s: ib_req_notify_cq failed: %i\n" ,
710
730
__func__ , rc );
711
731
goto out2 ;
712
732
}
713
733
714
- ep -> rep_attr .send_cq = ep -> rep_cq ;
715
- ep -> rep_attr .recv_cq = ep -> rep_cq ;
734
+ recvcq = ib_create_cq (ia -> ri_id -> device , rpcrdma_recvcq_upcall ,
735
+ rpcrdma_cq_async_error_upcall , NULL ,
736
+ ep -> rep_attr .cap .max_recv_wr + 1 , 0 );
737
+ if (IS_ERR (recvcq )) {
738
+ rc = PTR_ERR (recvcq );
739
+ dprintk ("RPC: %s: failed to create recv CQ: %i\n" ,
740
+ __func__ , rc );
741
+ goto out2 ;
742
+ }
743
+
744
+ rc = ib_req_notify_cq (recvcq , IB_CQ_NEXT_COMP );
745
+ if (rc ) {
746
+ dprintk ("RPC: %s: ib_req_notify_cq failed: %i\n" ,
747
+ __func__ , rc );
748
+ ib_destroy_cq (recvcq );
749
+ goto out2 ;
750
+ }
751
+
752
+ ep -> rep_attr .send_cq = sendcq ;
753
+ ep -> rep_attr .recv_cq = recvcq ;
716
754
717
755
/* Initialize cma parameters */
718
756
@@ -734,7 +772,7 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
734
772
return 0 ;
735
773
736
774
out2 :
737
- err = ib_destroy_cq (ep -> rep_cq );
775
+ err = ib_destroy_cq (sendcq );
738
776
if (err )
739
777
dprintk ("RPC: %s: ib_destroy_cq returned %i\n" ,
740
778
__func__ , err );
@@ -774,8 +812,14 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
774
812
ep -> rep_pad_mr = NULL ;
775
813
}
776
814
777
- rpcrdma_clean_cq (ep -> rep_cq );
778
- rc = ib_destroy_cq (ep -> rep_cq );
815
+ rpcrdma_clean_cq (ep -> rep_attr .recv_cq );
816
+ rc = ib_destroy_cq (ep -> rep_attr .recv_cq );
817
+ if (rc )
818
+ dprintk ("RPC: %s: ib_destroy_cq returned %i\n" ,
819
+ __func__ , rc );
820
+
821
+ rpcrdma_clean_cq (ep -> rep_attr .send_cq );
822
+ rc = ib_destroy_cq (ep -> rep_attr .send_cq );
779
823
if (rc )
780
824
dprintk ("RPC: %s: ib_destroy_cq returned %i\n" ,
781
825
__func__ , rc );
@@ -798,7 +842,9 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
798
842
if (rc && rc != - ENOTCONN )
799
843
dprintk ("RPC: %s: rpcrdma_ep_disconnect"
800
844
" status %i\n" , __func__ , rc );
801
- rpcrdma_clean_cq (ep -> rep_cq );
845
+
846
+ rpcrdma_clean_cq (ep -> rep_attr .recv_cq );
847
+ rpcrdma_clean_cq (ep -> rep_attr .send_cq );
802
848
803
849
xprt = container_of (ia , struct rpcrdma_xprt , rx_ia );
804
850
id = rpcrdma_create_id (xprt , ia ,
@@ -907,7 +953,8 @@ rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
907
953
{
908
954
int rc ;
909
955
910
- rpcrdma_clean_cq (ep -> rep_cq );
956
+ rpcrdma_clean_cq (ep -> rep_attr .recv_cq );
957
+ rpcrdma_clean_cq (ep -> rep_attr .send_cq );
911
958
rc = rdma_disconnect (ia -> ri_id );
912
959
if (!rc ) {
913
960
/* returns without wait if not connected */
@@ -1727,7 +1774,6 @@ rpcrdma_ep_post_recv(struct rpcrdma_ia *ia,
1727
1774
ib_dma_sync_single_for_cpu (ia -> ri_id -> device ,
1728
1775
rep -> rr_iov .addr , rep -> rr_iov .length , DMA_BIDIRECTIONAL );
1729
1776
1730
- DECR_CQCOUNT (ep );
1731
1777
rc = ib_post_recv (ia -> ri_id -> qp , & recv_wr , & recv_wr_fail );
1732
1778
1733
1779
if (rc )
0 commit comments