net/smc: prepare for more proposed ISM devices
authorUrsula Braun <ubraun@linux.ibm.com>
Sat, 26 Sep 2020 10:44:23 +0000 (12:44 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Sep 2020 22:19:02 +0000 (15:19 -0700)
SMCD Version 2 allows proposing of up to 8 ISM devices in addition
to the native ISM device of SMCD Version 1.
This patch prepares the struct smc_init_info to deal with these
additional 8 ISM devices.

Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/smc/af_smc.c
net/smc/smc.h
net/smc/smc_clc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_pnet.c

index 9114827..dc0049b 100644 (file)
@@ -564,7 +564,7 @@ static int smc_find_ism_device(struct smc_sock *smc, struct smc_init_info *ini)
 {
        /* Find ISM device with same PNETID as connecting interface  */
        smc_pnet_find_ism_resource(smc->clcsock->sk, ini);
-       if (!ini->ism_dev)
+       if (!ini->ism_dev[0])
                return SMC_CLC_DECL_NOSMCDDEV;
        return 0;
 }
@@ -573,7 +573,7 @@ static int smc_find_ism_device(struct smc_sock *smc, struct smc_init_info *ini)
 static int smc_connect_ism_vlan_setup(struct smc_sock *smc,
                                      struct smc_init_info *ini)
 {
-       if (ini->vlan_id && smc_ism_get_vlan(ini->ism_dev, ini->vlan_id))
+       if (ini->vlan_id && smc_ism_get_vlan(ini->ism_dev[0], ini->vlan_id))
                return SMC_CLC_DECL_ISMVLANERR;
        return 0;
 }
@@ -586,7 +586,7 @@ static int smc_connect_ism_vlan_cleanup(struct smc_sock *smc, bool is_smcd,
 {
        if (!is_smcd)
                return 0;
-       if (ini->vlan_id && smc_ism_put_vlan(ini->ism_dev, ini->vlan_id))
+       if (ini->vlan_id && smc_ism_put_vlan(ini->ism_dev[0], ini->vlan_id))
                return SMC_CLC_DECL_CNFERR;
        return 0;
 }
@@ -712,7 +712,7 @@ static int smc_connect_ism(struct smc_sock *smc,
        int rc = 0;
 
        ini->is_smcd = true;
-       ini->ism_peer_gid = aclc->d0.gid;
+       ini->ism_peer_gid[0] = aclc->d0.gid;
        ini->first_contact_peer = aclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK;
 
        /* there is only one lgr role for SMC-D; use server lock */
@@ -754,7 +754,7 @@ static int __smc_connect(struct smc_sock *smc)
 {
        bool ism_supported = false, rdma_supported = false;
        struct smc_clc_msg_accept_confirm aclc;
-       struct smc_init_info ini = {0};
+       struct smc_init_info *ini = NULL;
        int smc_type;
        int rc = 0;
 
@@ -769,21 +769,27 @@ static int __smc_connect(struct smc_sock *smc)
        if (using_ipsec(smc))
                return smc_connect_decline_fallback(smc, SMC_CLC_DECL_IPSEC);
 
+       ini = kzalloc(sizeof(*ini), GFP_KERNEL);
+       if (!ini)
+               return smc_connect_decline_fallback(smc, SMC_CLC_DECL_MEM);
+
        /* get vlan id from IP device */
-       if (smc_vlan_by_tcpsk(smc->clcsock, &ini))
+       if (smc_vlan_by_tcpsk(smc->clcsock, ini)) {
+               kfree(ini);
                return smc_connect_decline_fallback(smc,
                                                    SMC_CLC_DECL_GETVLANERR);
+       }
 
        /* check if there is an ism device available */
-       if (!smc_find_ism_device(smc, &ini) &&
-           !smc_connect_ism_vlan_setup(smc, &ini)) {
+       if (!smc_find_ism_device(smc, ini) &&
+           !smc_connect_ism_vlan_setup(smc, ini)) {
                /* ISM is supported for this connection */
                ism_supported = true;
                smc_type = SMC_TYPE_D;
        }
 
        /* check if there is a rdma device available */
-       if (!smc_find_rdma_device(smc, &ini)) {
+       if (!smc_find_rdma_device(smc, ini)) {
                /* RDMA is supported for this connection */
                rdma_supported = true;
                if (ism_supported)
@@ -793,29 +799,34 @@ static int __smc_connect(struct smc_sock *smc)
        }
 
        /* if neither ISM nor RDMA are supported, fallback */
-       if (!rdma_supported && !ism_supported)
+       if (!rdma_supported && !ism_supported) {
+               kfree(ini);
                return smc_connect_decline_fallback(smc, SMC_CLC_DECL_NOSMCDEV);
+       }
 
        /* perform CLC handshake */
-       rc = smc_connect_clc(smc, smc_type, &aclc, &ini);
+       rc = smc_connect_clc(smc, smc_type, &aclc, ini);
        if (rc) {
-               smc_connect_ism_vlan_cleanup(smc, ism_supported, &ini);
+               smc_connect_ism_vlan_cleanup(smc, ism_supported, ini);
+               kfree(ini);
                return smc_connect_decline_fallback(smc, rc);
        }
 
        /* depending on previous steps, connect using rdma or ism */
        if (rdma_supported && aclc.hdr.typev1 == SMC_TYPE_R)
-               rc = smc_connect_rdma(smc, &aclc, &ini);
+               rc = smc_connect_rdma(smc, &aclc, ini);
        else if (ism_supported && aclc.hdr.typev1 == SMC_TYPE_D)
-               rc = smc_connect_ism(smc, &aclc, &ini);
+               rc = smc_connect_ism(smc, &aclc, ini);
        else
                rc = SMC_CLC_DECL_MODEUNSUPP;
        if (rc) {
-               smc_connect_ism_vlan_cleanup(smc, ism_supported, &ini);
+               smc_connect_ism_vlan_cleanup(smc, ism_supported, ini);
+               kfree(ini);
                return smc_connect_decline_fallback(smc, rc);
        }
 
-       smc_connect_ism_vlan_cleanup(smc, ism_supported, &ini);
+       smc_connect_ism_vlan_cleanup(smc, ism_supported, ini);
+       kfree(ini);
        return 0;
 }
 
@@ -1219,14 +1230,14 @@ static void smc_find_ism_device_serv(struct smc_sock *new_smc,
        if (!smcd_indicated(pclc->hdr.typev1))
                goto not_found;
        ini->is_smcd = true; /* prepare ISM check */
-       ini->ism_peer_gid = pclc_smcd->gid;
+       ini->ism_peer_gid[0] = pclc_smcd->gid;
        if (smc_find_ism_device(new_smc, ini))
                goto not_found;
        if (!smc_listen_ism_init(new_smc, ini))
                return;         /* ISM device found */
 
 not_found:
-       ini->ism_dev = NULL;
+       ini->ism_dev[0] = NULL;
        ini->is_smcd = false;
 }
 
@@ -1319,7 +1330,7 @@ static void smc_listen_work(struct work_struct *work)
        struct smc_clc_msg_accept_confirm cclc;
        struct smc_clc_msg_proposal_area *buf;
        struct smc_clc_msg_proposal *pclc;
-       struct smc_init_info ini = {0};
+       struct smc_init_info *ini = NULL;
        int rc = 0;
 
        if (new_smc->listen_smc->sk.sk_state != SMC_LISTEN)
@@ -1363,8 +1374,14 @@ static void smc_listen_work(struct work_struct *work)
        if (rc)
                goto out_decl;
 
+       ini = kzalloc(sizeof(*ini), GFP_KERNEL);
+       if (!ini) {
+               rc = SMC_CLC_DECL_MEM;
+               goto out_decl;
+       }
+
        /* get vlan id from IP device */
-       if (smc_vlan_by_tcpsk(new_smc->clcsock, &ini)) {
+       if (smc_vlan_by_tcpsk(new_smc->clcsock, ini)) {
                rc = SMC_CLC_DECL_GETVLANERR;
                goto out_decl;
        }
@@ -1375,32 +1392,32 @@ static void smc_listen_work(struct work_struct *work)
        smc_tx_init(new_smc);
 
        /* determine ISM or RoCE device used for connection */
-       rc = smc_listen_find_device(new_smc, pclc, &ini);
+       rc = smc_listen_find_device(new_smc, pclc, ini);
        if (rc)
                goto out_unlock;
 
        /* send SMC Accept CLC message */
-       rc = smc_clc_send_accept(new_smc, ini.first_contact_local);
+       rc = smc_clc_send_accept(new_smc, ini->first_contact_local);
        if (rc)
                goto out_unlock;
 
        /* SMC-D does not need this lock any more */
-       if (ini.is_smcd)
+       if (ini->is_smcd)
                mutex_unlock(&smc_server_lgr_pending);
 
        /* receive SMC Confirm CLC message */
        rc = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
                              SMC_CLC_CONFIRM, CLC_WAIT_TIME);
        if (rc) {
-               if (!ini.is_smcd)
+               if (!ini->is_smcd)
                        goto out_unlock;
                goto out_decl;
        }
 
        /* finish worker */
-       if (!ini.is_smcd) {
+       if (!ini->is_smcd) {
                rc = smc_listen_rdma_finish(new_smc, &cclc,
-                                           ini.first_contact_local);
+                                           ini->first_contact_local);
                if (rc)
                        goto out_unlock;
                mutex_unlock(&smc_server_lgr_pending);
@@ -1412,8 +1429,9 @@ static void smc_listen_work(struct work_struct *work)
 out_unlock:
        mutex_unlock(&smc_server_lgr_pending);
 out_decl:
-       smc_listen_decline(new_smc, rc, ini.first_contact_local);
+       smc_listen_decline(new_smc, rc, ini ? ini->first_contact_local : 0);
 out_free:
+       kfree(ini);
        kfree(buf);
 }
 
index 2bd57e5..6c89cb8 100644 (file)
 #define SMCPROTO_SMC           0       /* SMC protocol, IPv4 */
 #define SMCPROTO_SMC6          1       /* SMC protocol, IPv6 */
 
+#define SMC_MAX_ISM_DEVS       8       /* max # of proposed non-native ISM
+                                        * devices
+                                        */
+
 extern struct proto smc_proto;
 extern struct proto smc_proto6;
 
index 3cc3a2e..684172d 100644 (file)
@@ -463,7 +463,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
                /* add SMC-D specifics */
                plen += sizeof(*pclc_smcd);
                pclc_base->iparea_offset = htons(sizeof(*pclc_smcd));
-               pclc_smcd->gid = ini->ism_dev->local_gid;
+               pclc_smcd->gid = ini->ism_dev[0]->local_gid;
        }
        pclc_base->hdr.length = htons(plen);
 
index c811ae1..26db5ef 100644 (file)
@@ -375,7 +375,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
        int i;
 
        if (ini->is_smcd && ini->vlan_id) {
-               if (smc_ism_get_vlan(ini->ism_dev, ini->vlan_id)) {
+               if (smc_ism_get_vlan(ini->ism_dev[0], ini->vlan_id)) {
                        rc = SMC_CLC_DECL_ISMVLANERR;
                        goto out;
                }
@@ -412,13 +412,13 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
        lgr->conns_all = RB_ROOT;
        if (ini->is_smcd) {
                /* SMC-D specific settings */
-               get_device(&ini->ism_dev->dev);
-               lgr->peer_gid = ini->ism_peer_gid;
-               lgr->smcd = ini->ism_dev;
-               lgr_list = &ini->ism_dev->lgr_list;
+               get_device(&ini->ism_dev[0]->dev);
+               lgr->peer_gid = ini->ism_peer_gid[0];
+               lgr->smcd = ini->ism_dev[0];
+               lgr_list = &ini->ism_dev[0]->lgr_list;
                lgr_lock = &lgr->smcd->lgr_lock;
                lgr->peer_shutdown = 0;
-               atomic_inc(&ini->ism_dev->lgr_cnt);
+               atomic_inc(&ini->ism_dev[0]->lgr_cnt);
        } else {
                /* SMC-R specific settings */
                lgr->role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
@@ -449,7 +449,7 @@ free_lgr:
        kfree(lgr);
 ism_put_vlan:
        if (ini->is_smcd && ini->vlan_id)
-               smc_ism_put_vlan(ini->ism_dev, ini->vlan_id);
+               smc_ism_put_vlan(ini->ism_dev[0], ini->vlan_id);
 out:
        if (rc < 0) {
                if (rc == -ENOMEM)
@@ -1288,8 +1288,10 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
        spinlock_t *lgr_lock;
        int rc = 0;
 
-       lgr_list = ini->is_smcd ? &ini->ism_dev->lgr_list : &smc_lgr_list.list;
-       lgr_lock = ini->is_smcd ? &ini->ism_dev->lgr_lock : &smc_lgr_list.lock;
+       lgr_list = ini->is_smcd ? &ini->ism_dev[0]->lgr_list :
+                                 &smc_lgr_list.list;
+       lgr_lock = ini->is_smcd ? &ini->ism_dev[0]->lgr_lock :
+                                 &smc_lgr_list.lock;
        ini->first_contact_local = 1;
        role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
        if (role == SMC_CLNT && ini->first_contact_peer)
@@ -1301,7 +1303,8 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
        list_for_each_entry(lgr, lgr_list, list) {
                write_lock_bh(&lgr->conns_lock);
                if ((ini->is_smcd ?
-                    smcd_lgr_match(lgr, ini->ism_dev, ini->ism_peer_gid) :
+                    smcd_lgr_match(lgr, ini->ism_dev[0],
+                                   ini->ism_peer_gid[0]) :
                     smcr_lgr_match(lgr, ini->ib_lcl, role, ini->ib_clcqpn)) &&
                    !lgr->sync_err &&
                    lgr->vlan_id == ini->vlan_id &&
index 37a5903..ec86084 100644 (file)
@@ -301,8 +301,8 @@ struct smc_init_info {
        u8                      ib_port;
        u32                     ib_clcqpn;
        /* SMC-D */
-       u64                     ism_peer_gid;
-       struct smcd_dev         *ism_dev;
+       u64                     ism_peer_gid[SMC_MAX_ISM_DEVS + 1];
+       struct smcd_dev         *ism_dev[SMC_MAX_ISM_DEVS + 1];
 };
 
 /* Find the connection associated with the given alert token in the link group.
index 0af5b4a..0b0f270 100644 (file)
@@ -933,10 +933,10 @@ static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev,
        list_for_each_entry(ismdev, &smcd_dev_list.list, list) {
                if (smc_pnet_match(ismdev->pnetid, ndev_pnetid) &&
                    !ismdev->going_away &&
-                   (!ini->ism_peer_gid ||
-                    !smc_ism_cantalk(ini->ism_peer_gid, ini->vlan_id,
+                   (!ini->ism_peer_gid[0] ||
+                    !smc_ism_cantalk(ini->ism_peer_gid[0], ini->vlan_id,
                                      ismdev))) {
-                       ini->ism_dev = ismdev;
+                       ini->ism_dev[0] = ismdev;
                        break;
                }
        }
@@ -970,7 +970,7 @@ void smc_pnet_find_ism_resource(struct sock *sk, struct smc_init_info *ini)
 {
        struct dst_entry *dst = sk_dst_get(sk);
 
-       ini->ism_dev = NULL;
+       ini->ism_dev[0] = NULL;
        if (!dst)
                goto out;
        if (!dst->dev)