@@ -172,6 +172,7 @@ static void smbd_disconnect_wake_up_all(struct smbdirect_socket *sc)
172172 * in order to notice the broken connection.
173173 */
174174 wake_up_all (& sc -> status_wait );
175+ wake_up_all (& sc -> send_io .lcredits .wait_queue );
175176 wake_up_all (& sc -> send_io .credits .wait_queue );
176177 wake_up_all (& sc -> send_io .pending .dec_wait_queue );
177178 wake_up_all (& sc -> send_io .pending .zero_wait_queue );
@@ -495,6 +496,7 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
495496 struct smbdirect_send_io * request =
496497 container_of (wc -> wr_cqe , struct smbdirect_send_io , cqe );
497498 struct smbdirect_socket * sc = request -> socket ;
499+ int lcredits = 0 ;
498500
499501 log_rdma_send (INFO , "smbdirect_send_io 0x%p completed wc->status=%s\n" ,
500502 request , ib_wc_status_msg (wc -> status ));
@@ -504,22 +506,24 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
504506 request -> sge [i ].addr ,
505507 request -> sge [i ].length ,
506508 DMA_TO_DEVICE );
509+ mempool_free (request , sc -> send_io .mem .pool );
510+ lcredits += 1 ;
507511
508512 if (wc -> status != IB_WC_SUCCESS || wc -> opcode != IB_WC_SEND ) {
509513 if (wc -> status != IB_WC_WR_FLUSH_ERR )
510514 log_rdma_send (ERR , "wc->status=%s wc->opcode=%d\n" ,
511515 ib_wc_status_msg (wc -> status ), wc -> opcode );
512- mempool_free (request , sc -> send_io .mem .pool );
513516 smbd_disconnect_rdma_connection (sc );
514517 return ;
515518 }
516519
520+ atomic_add (lcredits , & sc -> send_io .lcredits .count );
521+ wake_up (& sc -> send_io .lcredits .wait_queue );
522+
517523 if (atomic_dec_and_test (& sc -> send_io .pending .count ))
518524 wake_up (& sc -> send_io .pending .zero_wait_queue );
519525
520526 wake_up (& sc -> send_io .pending .dec_wait_queue );
521-
522- mempool_free (request , sc -> send_io .mem .pool );
523527}
524528
525529static void dump_smbdirect_negotiate_resp (struct smbdirect_negotiate_resp * resp )
@@ -567,6 +571,7 @@ static bool process_negotiation_response(
567571 log_rdma_event (ERR , "error: credits_granted==0\n" );
568572 return false;
569573 }
574+ atomic_set (& sc -> send_io .lcredits .count , sp -> send_credit_target );
570575 atomic_set (& sc -> send_io .credits .count , le16_to_cpu (packet -> credits_granted ));
571576
572577 if (le32_to_cpu (packet -> preferred_send_size ) > sp -> max_recv_size ) {
@@ -1114,6 +1119,24 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
11141119 struct smbdirect_data_transfer * packet ;
11151120 int new_credits = 0 ;
11161121
1122+ wait_lcredit :
1123+ /* Wait for local send credits */
1124+ rc = wait_event_interruptible (sc -> send_io .lcredits .wait_queue ,
1125+ atomic_read (& sc -> send_io .lcredits .count ) > 0 ||
1126+ sc -> status != SMBDIRECT_SOCKET_CONNECTED );
1127+ if (rc )
1128+ goto err_wait_lcredit ;
1129+
1130+ if (sc -> status != SMBDIRECT_SOCKET_CONNECTED ) {
1131+ log_outgoing (ERR , "disconnected not sending on wait_credit\n" );
1132+ rc = - EAGAIN ;
1133+ goto err_wait_lcredit ;
1134+ }
1135+ if (unlikely (atomic_dec_return (& sc -> send_io .lcredits .count ) < 0 )) {
1136+ atomic_inc (& sc -> send_io .lcredits .count );
1137+ goto wait_lcredit ;
1138+ }
1139+
11171140wait_credit :
11181141 /* Wait for send credits. A SMBD packet needs one credit */
11191142 rc = wait_event_interruptible (sc -> send_io .credits .wait_queue ,
@@ -1132,23 +1155,6 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
11321155 goto wait_credit ;
11331156 }
11341157
1135- wait_send_queue :
1136- wait_event (sc -> send_io .pending .dec_wait_queue ,
1137- atomic_read (& sc -> send_io .pending .count ) < sp -> send_credit_target ||
1138- sc -> status != SMBDIRECT_SOCKET_CONNECTED );
1139-
1140- if (sc -> status != SMBDIRECT_SOCKET_CONNECTED ) {
1141- log_outgoing (ERR , "disconnected not sending on wait_send_queue\n" );
1142- rc = - EAGAIN ;
1143- goto err_wait_send_queue ;
1144- }
1145-
1146- if (unlikely (atomic_inc_return (& sc -> send_io .pending .count ) >
1147- sp -> send_credit_target )) {
1148- atomic_dec (& sc -> send_io .pending .count );
1149- goto wait_send_queue ;
1150- }
1151-
11521158 request = mempool_alloc (sc -> send_io .mem .pool , GFP_KERNEL );
11531159 if (!request ) {
11541160 rc = - ENOMEM ;
@@ -1229,10 +1235,21 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
12291235 le32_to_cpu (packet -> data_length ),
12301236 le32_to_cpu (packet -> remaining_data_length ));
12311237
1238+ /*
1239+ * Now that we got a local and a remote credit
1240+ * we add us as pending
1241+ */
1242+ atomic_inc (& sc -> send_io .pending .count );
1243+
12321244 rc = smbd_post_send (sc , request );
12331245 if (!rc )
12341246 return 0 ;
12351247
1248+ if (atomic_dec_and_test (& sc -> send_io .pending .count ))
1249+ wake_up (& sc -> send_io .pending .zero_wait_queue );
1250+
1251+ wake_up (& sc -> send_io .pending .dec_wait_queue );
1252+
12361253err_dma :
12371254 for (i = 0 ; i < request -> num_sge ; i ++ )
12381255 if (request -> sge [i ].addr )
@@ -1246,14 +1263,14 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
12461263 atomic_sub (new_credits , & sc -> recv_io .credits .count );
12471264
12481265err_alloc :
1249- if (atomic_dec_and_test (& sc -> send_io .pending .count ))
1250- wake_up (& sc -> send_io .pending .zero_wait_queue );
1251-
1252- err_wait_send_queue :
1253- /* roll back send credits and pending */
12541266 atomic_inc (& sc -> send_io .credits .count );
1267+ wake_up (& sc -> send_io .credits .wait_queue );
12551268
12561269err_wait_credit :
1270+ atomic_inc (& sc -> send_io .lcredits .count );
1271+ wake_up (& sc -> send_io .lcredits .wait_queue );
1272+
1273+ err_wait_lcredit :
12571274 return rc ;
12581275}
12591276
0 commit comments