2020#include "smc_loopback.h"
2121
2222#define SMC_LO_V2_CAPABLE 0x1 /* loopback-ism acts as ISMv2 */
23+ #define SMC_LO_SUPPORT_NOCOPY 0x1
2324#define SMC_DMA_ADDR_INVALID (~(dma_addr_t)0)
2425
2526static const char smc_lo_dev_name [] = "loopback-ism" ;
@@ -81,6 +82,7 @@ static int smc_lo_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
8182 goto err_node ;
8283 }
8384 dmb_node -> dma_addr = SMC_DMA_ADDR_INVALID ;
85+ refcount_set (& dmb_node -> refcnt , 1 );
8486
8587again :
8688 /* add new dmb into hash table */
@@ -94,6 +96,7 @@ static int smc_lo_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
9496 }
9597 hash_add (ldev -> dmb_ht , & dmb_node -> list , dmb_node -> token );
9698 write_unlock_bh (& ldev -> dmb_ht_lock );
99+ atomic_inc (& ldev -> dmb_cnt );
97100
98101 dmb -> sba_idx = dmb_node -> sba_idx ;
99102 dmb -> dmb_tok = dmb_node -> token ;
@@ -110,30 +113,106 @@ static int smc_lo_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
110113 return rc ;
111114}
112115
116+ static void __smc_lo_unregister_dmb (struct smc_lo_dev * ldev ,
117+ struct smc_lo_dmb_node * dmb_node )
118+ {
119+ /* remove dmb from hash table */
120+ write_lock_bh (& ldev -> dmb_ht_lock );
121+ hash_del (& dmb_node -> list );
122+ write_unlock_bh (& ldev -> dmb_ht_lock );
123+
124+ clear_bit (dmb_node -> sba_idx , ldev -> sba_idx_mask );
125+ kvfree (dmb_node -> cpu_addr );
126+ kfree (dmb_node );
127+
128+ if (atomic_dec_and_test (& ldev -> dmb_cnt ))
129+ wake_up (& ldev -> ldev_release );
130+ }
131+
113132static int smc_lo_unregister_dmb (struct smcd_dev * smcd , struct smcd_dmb * dmb )
114133{
115134 struct smc_lo_dmb_node * dmb_node = NULL , * tmp_node ;
116135 struct smc_lo_dev * ldev = smcd -> priv ;
117136
118- /* remove dmb from hash table */
119- write_lock_bh (& ldev -> dmb_ht_lock );
137+ /* find dmb from hash table */
138+ read_lock_bh (& ldev -> dmb_ht_lock );
120139 hash_for_each_possible (ldev -> dmb_ht , tmp_node , list , dmb -> dmb_tok ) {
121140 if (tmp_node -> token == dmb -> dmb_tok ) {
122141 dmb_node = tmp_node ;
123142 break ;
124143 }
125144 }
126145 if (!dmb_node ) {
127- write_unlock_bh (& ldev -> dmb_ht_lock );
146+ read_unlock_bh (& ldev -> dmb_ht_lock );
128147 return - EINVAL ;
129148 }
130- hash_del (& dmb_node -> list );
131- write_unlock_bh (& ldev -> dmb_ht_lock );
149+ read_unlock_bh (& ldev -> dmb_ht_lock );
132150
133- clear_bit (dmb_node -> sba_idx , ldev -> sba_idx_mask );
134- kfree (dmb_node -> cpu_addr );
135- kfree (dmb_node );
151+ if (refcount_dec_and_test (& dmb_node -> refcnt ))
152+ __smc_lo_unregister_dmb (ldev , dmb_node );
153+ return 0 ;
154+ }
155+
156+ static int smc_lo_support_dmb_nocopy (struct smcd_dev * smcd )
157+ {
158+ return SMC_LO_SUPPORT_NOCOPY ;
159+ }
160+
161+ static int smc_lo_attach_dmb (struct smcd_dev * smcd , struct smcd_dmb * dmb )
162+ {
163+ struct smc_lo_dmb_node * dmb_node = NULL , * tmp_node ;
164+ struct smc_lo_dev * ldev = smcd -> priv ;
165+
166+ /* find dmb_node according to dmb->dmb_tok */
167+ read_lock_bh (& ldev -> dmb_ht_lock );
168+ hash_for_each_possible (ldev -> dmb_ht , tmp_node , list , dmb -> dmb_tok ) {
169+ if (tmp_node -> token == dmb -> dmb_tok ) {
170+ dmb_node = tmp_node ;
171+ break ;
172+ }
173+ }
174+ if (!dmb_node ) {
175+ read_unlock_bh (& ldev -> dmb_ht_lock );
176+ return - EINVAL ;
177+ }
178+ read_unlock_bh (& ldev -> dmb_ht_lock );
179+
180+ if (!refcount_inc_not_zero (& dmb_node -> refcnt ))
181+ /* the dmb is being unregistered, but has
182+ * not been removed from the hash table.
183+ */
184+ return - EINVAL ;
136185
186+ /* provide dmb information */
187+ dmb -> sba_idx = dmb_node -> sba_idx ;
188+ dmb -> dmb_tok = dmb_node -> token ;
189+ dmb -> cpu_addr = dmb_node -> cpu_addr ;
190+ dmb -> dma_addr = dmb_node -> dma_addr ;
191+ dmb -> dmb_len = dmb_node -> len ;
192+ return 0 ;
193+ }
194+
195+ static int smc_lo_detach_dmb (struct smcd_dev * smcd , u64 token )
196+ {
197+ struct smc_lo_dmb_node * dmb_node = NULL , * tmp_node ;
198+ struct smc_lo_dev * ldev = smcd -> priv ;
199+
200+ /* find dmb_node according to dmb->dmb_tok */
201+ read_lock_bh (& ldev -> dmb_ht_lock );
202+ hash_for_each_possible (ldev -> dmb_ht , tmp_node , list , token ) {
203+ if (tmp_node -> token == token ) {
204+ dmb_node = tmp_node ;
205+ break ;
206+ }
207+ }
208+ if (!dmb_node ) {
209+ read_unlock_bh (& ldev -> dmb_ht_lock );
210+ return - EINVAL ;
211+ }
212+ read_unlock_bh (& ldev -> dmb_ht_lock );
213+
214+ if (refcount_dec_and_test (& dmb_node -> refcnt ))
215+ __smc_lo_unregister_dmb (ldev , dmb_node );
137216 return 0 ;
138217}
139218
@@ -145,6 +224,12 @@ static int smc_lo_move_data(struct smcd_dev *smcd, u64 dmb_tok,
145224 struct smc_lo_dev * ldev = smcd -> priv ;
146225 struct smc_connection * conn ;
147226
227+ if (!sf )
228+ /* since sndbuf is merged with peer DMB, there is
229+ * no need to copy data from sndbuf to peer DMB.
230+ */
231+ return 0 ;
232+
148233 read_lock_bh (& ldev -> dmb_ht_lock );
149234 hash_for_each_possible (ldev -> dmb_ht , tmp_node , list , dmb_tok ) {
150235 if (tmp_node -> token == dmb_tok ) {
@@ -159,13 +244,10 @@ static int smc_lo_move_data(struct smcd_dev *smcd, u64 dmb_tok,
159244 memcpy ((char * )rmb_node -> cpu_addr + offset , data , size );
160245 read_unlock_bh (& ldev -> dmb_ht_lock );
161246
162- if (sf ) {
163- conn = smcd -> conn [rmb_node -> sba_idx ];
164- if (conn && !conn -> killed )
165- tasklet_schedule (& conn -> rx_tsklet );
166- else
167- return - EPIPE ;
168- }
247+ conn = smcd -> conn [rmb_node -> sba_idx ];
248+ if (!conn || conn -> killed )
249+ return - EPIPE ;
250+ tasklet_schedule (& conn -> rx_tsklet );
169251 return 0 ;
170252}
171253
@@ -197,6 +279,9 @@ static const struct smcd_ops lo_ops = {
197279 .query_remote_gid = smc_lo_query_rgid ,
198280 .register_dmb = smc_lo_register_dmb ,
199281 .unregister_dmb = smc_lo_unregister_dmb ,
282+ .support_dmb_nocopy = smc_lo_support_dmb_nocopy ,
283+ .attach_dmb = smc_lo_attach_dmb ,
284+ .detach_dmb = smc_lo_detach_dmb ,
200285 .add_vlan_id = NULL ,
201286 .del_vlan_id = NULL ,
202287 .set_vlan_required = NULL ,
@@ -275,12 +360,17 @@ static int smc_lo_dev_init(struct smc_lo_dev *ldev)
275360 smc_lo_generate_ids (ldev );
276361 rwlock_init (& ldev -> dmb_ht_lock );
277362 hash_init (ldev -> dmb_ht );
363+ atomic_set (& ldev -> dmb_cnt , 0 );
364+ init_waitqueue_head (& ldev -> ldev_release );
365+
278366 return smcd_lo_register_dev (ldev );
279367}
280368
281369static void smc_lo_dev_exit (struct smc_lo_dev * ldev )
282370{
283371 smcd_lo_unregister_dev (ldev );
372+ if (atomic_read (& ldev -> dmb_cnt ))
373+ wait_event (ldev -> ldev_release , !atomic_read (& ldev -> dmb_cnt ));
284374}
285375
286376static void smc_lo_dev_release (struct device * dev )
0 commit comments