@@ -117,7 +117,7 @@ int smc_cdc_msg_send(struct smc_connection *conn,
117117 return rc ;
118118}
119119
120- int smc_cdc_get_slot_and_msg_send (struct smc_connection * conn )
120+ static int smcr_cdc_get_slot_and_msg_send (struct smc_connection * conn )
121121{
122122 struct smc_cdc_tx_pend * pend ;
123123 struct smc_wr_buf * wr_buf ;
@@ -130,6 +130,21 @@ int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn)
130130 return smc_cdc_msg_send (conn , wr_buf , pend );
131131}
132132
133+ int smc_cdc_get_slot_and_msg_send (struct smc_connection * conn )
134+ {
135+ int rc ;
136+
137+ if (conn -> lgr -> is_smcd ) {
138+ spin_lock_bh (& conn -> send_lock );
139+ rc = smcd_cdc_msg_send (conn );
140+ spin_unlock_bh (& conn -> send_lock );
141+ } else {
142+ rc = smcr_cdc_get_slot_and_msg_send (conn );
143+ }
144+
145+ return rc ;
146+ }
147+
133148static bool smc_cdc_tx_filter (struct smc_wr_tx_pend_priv * tx_pend ,
134149 unsigned long data )
135150{
@@ -157,6 +172,45 @@ void smc_cdc_tx_dismiss_slots(struct smc_connection *conn)
157172 (unsigned long )conn );
158173}
159174
175+ /* Send a SMC-D CDC header.
176+ * This increments the free space available in our send buffer.
177+ * Also update the confirmed receive buffer with what was sent to the peer.
178+ */
179+ int smcd_cdc_msg_send (struct smc_connection * conn )
180+ {
181+ struct smc_sock * smc = container_of (conn , struct smc_sock , conn );
182+ struct smcd_cdc_msg cdc ;
183+ int rc , diff ;
184+
185+ memset (& cdc , 0 , sizeof (cdc ));
186+ cdc .common .type = SMC_CDC_MSG_TYPE ;
187+ cdc .prod_wrap = conn -> local_tx_ctrl .prod .wrap ;
188+ cdc .prod_count = conn -> local_tx_ctrl .prod .count ;
189+
190+ cdc .cons_wrap = conn -> local_tx_ctrl .cons .wrap ;
191+ cdc .cons_count = conn -> local_tx_ctrl .cons .count ;
192+ cdc .prod_flags = conn -> local_tx_ctrl .prod_flags ;
193+ cdc .conn_state_flags = conn -> local_tx_ctrl .conn_state_flags ;
194+ rc = smcd_tx_ism_write (conn , & cdc , sizeof (cdc ), 0 , 1 );
195+ if (rc )
196+ return rc ;
197+ smc_curs_write (& conn -> rx_curs_confirmed ,
198+ smc_curs_read (& conn -> local_tx_ctrl .cons , conn ), conn );
199+ /* Calculate transmitted data and increment free send buffer space */
200+ diff = smc_curs_diff (conn -> sndbuf_desc -> len , & conn -> tx_curs_fin ,
201+ & conn -> tx_curs_sent );
202+ /* increased by confirmed number of bytes */
203+ smp_mb__before_atomic ();
204+ atomic_add (diff , & conn -> sndbuf_space );
205+ /* guarantee 0 <= sndbuf_space <= sndbuf_desc->len */
206+ smp_mb__after_atomic ();
207+ smc_curs_write (& conn -> tx_curs_fin ,
208+ smc_curs_read (& conn -> tx_curs_sent , conn ), conn );
209+
210+ smc_tx_sndbuf_nonfull (smc );
211+ return rc ;
212+ }
213+
160214/********************************* receive ***********************************/
161215
162216static inline bool smc_cdc_before (u16 seq1 , u16 seq2 )
@@ -178,7 +232,7 @@ static void smc_cdc_handle_urg_data_arrival(struct smc_sock *smc,
178232 if (!sock_flag (& smc -> sk , SOCK_URGINLINE ))
179233 /* we'll skip the urgent byte, so don't account for it */
180234 (* diff_prod )-- ;
181- base = (char * )conn -> rmb_desc -> cpu_addr ;
235+ base = (char * )conn -> rmb_desc -> cpu_addr + conn -> rx_off ;
182236 if (conn -> urg_curs .count )
183237 conn -> urg_rx_byte = * (base + conn -> urg_curs .count - 1 );
184238 else
@@ -276,6 +330,34 @@ static void smc_cdc_msg_recv(struct smc_sock *smc, struct smc_cdc_msg *cdc)
276330 sock_put (& smc -> sk ); /* no free sk in softirq-context */
277331}
278332
333+ /* Schedule a tasklet for this connection. Triggered from the ISM device IRQ
334+ * handler to indicate update in the DMBE.
335+ *
336+ * Context:
337+ * - tasklet context
338+ */
339+ static void smcd_cdc_rx_tsklet (unsigned long data )
340+ {
341+ struct smc_connection * conn = (struct smc_connection * )data ;
342+ struct smcd_cdc_msg cdc ;
343+ struct smc_sock * smc ;
344+
345+ if (!conn )
346+ return ;
347+
348+ memcpy (& cdc , conn -> rmb_desc -> cpu_addr , sizeof (cdc ));
349+ smc = container_of (conn , struct smc_sock , conn );
350+ smc_cdc_msg_recv (smc , (struct smc_cdc_msg * )& cdc );
351+ }
352+
353+ /* Initialize receive tasklet. Called from ISM device IRQ handler to start
354+ * receiver side.
355+ */
356+ void smcd_cdc_rx_init (struct smc_connection * conn )
357+ {
358+ tasklet_init (& conn -> rx_tsklet , smcd_cdc_rx_tsklet , (unsigned long )conn );
359+ }
360+
279361/***************************** init, exit, misc ******************************/
280362
281363static void smc_cdc_rx_handler (struct ib_wc * wc , void * buf )
0 commit comments