1515#include <linux/types.h>
1616#include <net/smc.h>
1717
18+ #include "smc_cdc.h"
1819#include "smc_ism.h"
1920#include "smc_loopback.h"
2021
2122#define SMC_LO_V2_CAPABLE 0x1 /* loopback-ism acts as ISMv2 */
23+ #define SMC_DMA_ADDR_INVALID (~(dma_addr_t)0)
2224
2325static const char smc_lo_dev_name [] = "loopback-ism" ;
2426static struct smc_lo_dev * lo_dev ;
@@ -48,6 +50,125 @@ static int smc_lo_query_rgid(struct smcd_dev *smcd, struct smcd_gid *rgid,
4850 return 0 ;
4951}
5052
53+ static int smc_lo_register_dmb (struct smcd_dev * smcd , struct smcd_dmb * dmb ,
54+ void * client_priv )
55+ {
56+ struct smc_lo_dmb_node * dmb_node , * tmp_node ;
57+ struct smc_lo_dev * ldev = smcd -> priv ;
58+ int sba_idx , rc ;
59+
60+ /* check space for new dmb */
61+ for_each_clear_bit (sba_idx , ldev -> sba_idx_mask , SMC_LO_MAX_DMBS ) {
62+ if (!test_and_set_bit (sba_idx , ldev -> sba_idx_mask ))
63+ break ;
64+ }
65+ if (sba_idx == SMC_LO_MAX_DMBS )
66+ return - ENOSPC ;
67+
68+ dmb_node = kzalloc (sizeof (* dmb_node ), GFP_KERNEL );
69+ if (!dmb_node ) {
70+ rc = - ENOMEM ;
71+ goto err_bit ;
72+ }
73+
74+ dmb_node -> sba_idx = sba_idx ;
75+ dmb_node -> len = dmb -> dmb_len ;
76+ dmb_node -> cpu_addr = kzalloc (dmb_node -> len , GFP_KERNEL |
77+ __GFP_NOWARN | __GFP_NORETRY |
78+ __GFP_NOMEMALLOC );
79+ if (!dmb_node -> cpu_addr ) {
80+ rc = - ENOMEM ;
81+ goto err_node ;
82+ }
83+ dmb_node -> dma_addr = SMC_DMA_ADDR_INVALID ;
84+
85+ again :
86+ /* add new dmb into hash table */
87+ get_random_bytes (& dmb_node -> token , sizeof (dmb_node -> token ));
88+ write_lock_bh (& ldev -> dmb_ht_lock );
89+ hash_for_each_possible (ldev -> dmb_ht , tmp_node , list , dmb_node -> token ) {
90+ if (tmp_node -> token == dmb_node -> token ) {
91+ write_unlock_bh (& ldev -> dmb_ht_lock );
92+ goto again ;
93+ }
94+ }
95+ hash_add (ldev -> dmb_ht , & dmb_node -> list , dmb_node -> token );
96+ write_unlock_bh (& ldev -> dmb_ht_lock );
97+
98+ dmb -> sba_idx = dmb_node -> sba_idx ;
99+ dmb -> dmb_tok = dmb_node -> token ;
100+ dmb -> cpu_addr = dmb_node -> cpu_addr ;
101+ dmb -> dma_addr = dmb_node -> dma_addr ;
102+ dmb -> dmb_len = dmb_node -> len ;
103+
104+ return 0 ;
105+
106+ err_node :
107+ kfree (dmb_node );
108+ err_bit :
109+ clear_bit (sba_idx , ldev -> sba_idx_mask );
110+ return rc ;
111+ }
112+
113+ static int smc_lo_unregister_dmb (struct smcd_dev * smcd , struct smcd_dmb * dmb )
114+ {
115+ struct smc_lo_dmb_node * dmb_node = NULL , * tmp_node ;
116+ struct smc_lo_dev * ldev = smcd -> priv ;
117+
118+ /* remove dmb from hash table */
119+ write_lock_bh (& ldev -> dmb_ht_lock );
120+ hash_for_each_possible (ldev -> dmb_ht , tmp_node , list , dmb -> dmb_tok ) {
121+ if (tmp_node -> token == dmb -> dmb_tok ) {
122+ dmb_node = tmp_node ;
123+ break ;
124+ }
125+ }
126+ if (!dmb_node ) {
127+ write_unlock_bh (& ldev -> dmb_ht_lock );
128+ return - EINVAL ;
129+ }
130+ hash_del (& dmb_node -> list );
131+ write_unlock_bh (& ldev -> dmb_ht_lock );
132+
133+ clear_bit (dmb_node -> sba_idx , ldev -> sba_idx_mask );
134+ kfree (dmb_node -> cpu_addr );
135+ kfree (dmb_node );
136+
137+ return 0 ;
138+ }
139+
140+ static int smc_lo_move_data (struct smcd_dev * smcd , u64 dmb_tok ,
141+ unsigned int idx , bool sf , unsigned int offset ,
142+ void * data , unsigned int size )
143+ {
144+ struct smc_lo_dmb_node * rmb_node = NULL , * tmp_node ;
145+ struct smc_lo_dev * ldev = smcd -> priv ;
146+ struct smc_connection * conn ;
147+
148+ read_lock_bh (& ldev -> dmb_ht_lock );
149+ hash_for_each_possible (ldev -> dmb_ht , tmp_node , list , dmb_tok ) {
150+ if (tmp_node -> token == dmb_tok ) {
151+ rmb_node = tmp_node ;
152+ break ;
153+ }
154+ }
155+ if (!rmb_node ) {
156+ read_unlock_bh (& ldev -> dmb_ht_lock );
157+ return - EINVAL ;
158+ }
159+ memcpy ((char * )rmb_node -> cpu_addr + offset , data , size );
160+ read_unlock_bh (& ldev -> dmb_ht_lock );
161+
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+ }
169+ return 0 ;
170+ }
171+
51172static int smc_lo_supports_v2 (void )
52173{
53174 return SMC_LO_V2_CAPABLE ;
@@ -74,14 +195,14 @@ static struct device *smc_lo_get_dev(struct smcd_dev *smcd)
74195
75196static const struct smcd_ops lo_ops = {
76197 .query_remote_gid = smc_lo_query_rgid ,
77- .register_dmb = NULL ,
78- .unregister_dmb = NULL ,
198+ .register_dmb = smc_lo_register_dmb ,
199+ .unregister_dmb = smc_lo_unregister_dmb ,
79200 .add_vlan_id = NULL ,
80201 .del_vlan_id = NULL ,
81202 .set_vlan_required = NULL ,
82203 .reset_vlan_required = NULL ,
83204 .signal_event = NULL ,
84- .move_data = NULL ,
205+ .move_data = smc_lo_move_data ,
85206 .supports_v2 = smc_lo_supports_v2 ,
86207 .get_local_gid = smc_lo_get_local_gid ,
87208 .get_chid = smc_lo_get_chid ,
@@ -146,6 +267,8 @@ static void smcd_lo_unregister_dev(struct smc_lo_dev *ldev)
146267static int smc_lo_dev_init (struct smc_lo_dev * ldev )
147268{
148269 smc_lo_generate_ids (ldev );
270+ rwlock_init (& ldev -> dmb_ht_lock );
271+ hash_init (ldev -> dmb_ht );
149272 return smcd_lo_register_dev (ldev );
150273}
151274
0 commit comments