net/smc: compatible with 128-bits extended GID of virtual ISM device
authorWen Gu <guwen@linux.alibaba.com>
Tue, 19 Dec 2023 14:26:13 +0000 (22:26 +0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 26 Dec 2023 20:24:33 +0000 (20:24 +0000)
According to virtual ISM support feature defined by SMCv2.1, GIDs of
virtual ISM device are UUIDs defined by RFC4122, which are 128-bits
long. So some adaptation work is required. And note that the GIDs of
existing platform firmware ISM devices still remain 64-bits long.

Signed-off-by: Wen Gu <guwen@linux.alibaba.com>
Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
12 files changed:
drivers/s390/net/ism_drv.c
include/net/smc.h
net/smc/af_smc.c
net/smc/smc.h
net/smc/smc_clc.c
net/smc/smc_clc.h
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_diag.c
net/smc/smc_ism.c
net/smc/smc_ism.h
net/smc/smc_pnet.c

index 81aabbf..34dd063 100644 (file)
@@ -743,10 +743,10 @@ static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid,
        return ism_cmd(ism, &cmd);
 }
 
-static int smcd_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid,
-                          u32 vid)
+static int smcd_query_rgid(struct smcd_dev *smcd, struct smcd_gid *rgid,
+                          u32 vid_valid, u32 vid)
 {
-       return ism_query_rgid(smcd->priv, rgid, vid_valid, vid);
+       return ism_query_rgid(smcd->priv, rgid->gid, vid_valid, vid);
 }
 
 static int smcd_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
@@ -797,10 +797,11 @@ static int ism_signal_ieq(struct ism_dev *ism, u64 rgid, u32 trigger_irq,
        return ism_cmd(ism, &cmd);
 }
 
-static int smcd_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq,
-                          u32 event_code, u64 info)
+static int smcd_signal_ieq(struct smcd_dev *smcd, struct smcd_gid *rgid,
+                          u32 trigger_irq, u32 event_code, u64 info)
 {
-       return ism_signal_ieq(smcd->priv, rgid, trigger_irq, event_code, info);
+       return ism_signal_ieq(smcd->priv, rgid->gid,
+                             trigger_irq, event_code, info);
 }
 
 static int smcd_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx,
@@ -821,9 +822,11 @@ static u64 ism_get_local_gid(struct ism_dev *ism)
        return ism->local_gid;
 }
 
-static u64 smcd_get_local_gid(struct smcd_dev *smcd)
+static void smcd_get_local_gid(struct smcd_dev *smcd,
+                              struct smcd_gid *smcd_gid)
 {
-       return ism_get_local_gid(smcd->priv);
+       smcd_gid->gid = ism_get_local_gid(smcd->priv);
+       smcd_gid->gid_ext = 0;
 }
 
 static u16 ism_get_chid(struct ism_dev *ism)
index a002552..a0dc118 100644 (file)
@@ -52,9 +52,14 @@ struct smcd_dmb {
 struct smcd_dev;
 struct ism_client;
 
+struct smcd_gid {
+       u64     gid;
+       u64     gid_ext;
+};
+
 struct smcd_ops {
-       int (*query_remote_gid)(struct smcd_dev *dev, u64 rgid, u32 vid_valid,
-                               u32 vid);
+       int (*query_remote_gid)(struct smcd_dev *dev, struct smcd_gid *rgid,
+                               u32 vid_valid, u32 vid);
        int (*register_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb,
                            struct ism_client *client);
        int (*unregister_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb);
@@ -62,14 +67,14 @@ struct smcd_ops {
        int (*del_vlan_id)(struct smcd_dev *dev, u64 vlan_id);
        int (*set_vlan_required)(struct smcd_dev *dev);
        int (*reset_vlan_required)(struct smcd_dev *dev);
-       int (*signal_event)(struct smcd_dev *dev, u64 rgid, u32 trigger_irq,
-                           u32 event_code, u64 info);
+       int (*signal_event)(struct smcd_dev *dev, struct smcd_gid *rgid,
+                           u32 trigger_irq, u32 event_code, u64 info);
        int (*move_data)(struct smcd_dev *dev, u64 dmb_tok, unsigned int idx,
                         bool sf, unsigned int offset, void *data,
                         unsigned int size);
        int (*supports_v2)(void);
        u8* (*get_system_eid)(void);
-       u64 (*get_local_gid)(struct smcd_dev *dev);
+       void (*get_local_gid)(struct smcd_dev *dev, struct smcd_gid *gid);
        u16 (*get_chid)(struct smcd_dev *dev);
        struct device* (*get_dev)(struct smcd_dev *dev);
 };
index c0d3852..a2cb30a 100644 (file)
@@ -1044,7 +1044,8 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
 {
        int rc = SMC_CLC_DECL_NOSMCDDEV;
        struct smcd_dev *smcd;
-       int i = 1;
+       int i = 1, entry = 1;
+       bool is_virtual;
        u16 chid;
 
        if (smcd_indicated(ini->smc_type_v1))
@@ -1056,14 +1057,23 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
                chid = smc_ism_get_chid(smcd);
                if (!smc_find_ism_v2_is_unique_chid(chid, ini, i))
                        continue;
+               is_virtual = __smc_ism_is_virtual(chid);
                if (!smc_pnet_is_pnetid_set(smcd->pnetid) ||
                    smc_pnet_is_ndev_pnetid(sock_net(&smc->sk), smcd->pnetid)) {
+                       if (is_virtual && entry == SMCD_CLC_MAX_V2_GID_ENTRIES)
+                               /* It's the last GID-CHID entry left in CLC
+                                * Proposal SMC-Dv2 extension, but a virtual
+                                * ISM device will take two entries. So give
+                                * up it and try the next potential ISM device.
+                                */
+                               continue;
                        ini->ism_dev[i] = smcd;
                        ini->ism_chid[i] = chid;
                        ini->is_smcd = true;
                        rc = 0;
                        i++;
-                       if (i > SMC_MAX_ISM_DEVS)
+                       entry = is_virtual ? entry + 2 : entry + 1;
+                       if (entry > SMCD_CLC_MAX_V2_GID_ENTRIES)
                                break;
                }
        }
@@ -1402,8 +1412,13 @@ static int smc_connect_ism(struct smc_sock *smc,
                rc = smc_v2_determine_accepted_chid(aclc, ini);
                if (rc)
                        return rc;
+
+               if (__smc_ism_is_virtual(ini->ism_chid[ini->ism_selected]))
+                       ini->ism_peer_gid[ini->ism_selected].gid_ext =
+                                               ntohll(aclc->d1.gid_ext);
+               /* for non-virtual ISM devices, peer gid_ext remains 0. */
        }
-       ini->ism_peer_gid[ini->ism_selected] = ntohll(aclc->d0.gid);
+       ini->ism_peer_gid[ini->ism_selected].gid = ntohll(aclc->d0.gid);
 
        /* there is only one lgr role for SMC-D; use server lock */
        mutex_lock(&smc_server_lgr_pending);
@@ -2088,7 +2103,8 @@ static bool smc_is_already_selected(struct smcd_dev *smcd,
 
 /* check for ISM devices matching proposed ISM devices */
 static void smc_check_ism_v2_match(struct smc_init_info *ini,
-                                  u16 proposed_chid, u64 proposed_gid,
+                                  u16 proposed_chid,
+                                  struct smcd_gid *proposed_gid,
                                   unsigned int *matches)
 {
        struct smcd_dev *smcd;
@@ -2100,7 +2116,11 @@ static void smc_check_ism_v2_match(struct smc_init_info *ini,
                        continue;
                if (smc_ism_get_chid(smcd) == proposed_chid &&
                    !smc_ism_cantalk(proposed_gid, ISM_RESERVED_VLANID, smcd)) {
-                       ini->ism_peer_gid[*matches] = proposed_gid;
+                       ini->ism_peer_gid[*matches].gid = proposed_gid->gid;
+                       if (__smc_ism_is_virtual(proposed_chid))
+                               ini->ism_peer_gid[*matches].gid_ext =
+                                                       proposed_gid->gid_ext;
+                               /* non-virtual ISM's peer gid_ext remains 0. */
                        ini->ism_dev[*matches] = smcd;
                        (*matches)++;
                        break;
@@ -2122,9 +2142,11 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
        struct smc_clc_v2_extension *smc_v2_ext;
        struct smc_clc_msg_smcd *pclc_smcd;
        unsigned int matches = 0;
+       struct smcd_gid smcd_gid;
        u8 smcd_version;
        u8 *eid = NULL;
        int i, rc;
+       u16 chid;
 
        if (!(ini->smcd_version & SMC_V2) || !smcd_indicated(ini->smc_type_v2))
                goto not_found;
@@ -2134,18 +2156,35 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
        smcd_v2_ext = smc_get_clc_smcd_v2_ext(smc_v2_ext);
 
        mutex_lock(&smcd_dev_list.mutex);
-       if (pclc_smcd->ism.chid)
+       if (pclc_smcd->ism.chid) {
                /* check for ISM device matching proposed native ISM device */
+               smcd_gid.gid = ntohll(pclc_smcd->ism.gid);
+               smcd_gid.gid_ext = 0;
                smc_check_ism_v2_match(ini, ntohs(pclc_smcd->ism.chid),
-                                      ntohll(pclc_smcd->ism.gid), &matches);
-       for (i = 1; i <= smc_v2_ext->hdr.ism_gid_cnt; i++) {
+                                      &smcd_gid, &matches);
+       }
+       for (i = 0; i < smc_v2_ext->hdr.ism_gid_cnt; i++) {
                /* check for ISM devices matching proposed non-native ISM
                 * devices
                 */
-               smc_check_ism_v2_match(ini,
-                                      ntohs(smcd_v2_ext->gidchid[i - 1].chid),
-                                      ntohll(smcd_v2_ext->gidchid[i - 1].gid),
-                                      &matches);
+               smcd_gid.gid = ntohll(smcd_v2_ext->gidchid[i].gid);
+               smcd_gid.gid_ext = 0;
+               chid = ntohs(smcd_v2_ext->gidchid[i].chid);
+               if (__smc_ism_is_virtual(chid)) {
+                       if ((i + 1) == smc_v2_ext->hdr.ism_gid_cnt ||
+                           chid != ntohs(smcd_v2_ext->gidchid[i + 1].chid))
+                               /* each virtual ISM device takes two GID-CHID
+                                * entries and CHID of the second entry repeats
+                                * that of the first entry.
+                                *
+                                * So check if the next GID-CHID entry exists
+                                * and both two entries' CHIDs are the same.
+                                */
+                               continue;
+                       smcd_gid.gid_ext =
+                               ntohll(smcd_v2_ext->gidchid[++i].gid);
+               }
+               smc_check_ism_v2_match(ini, chid, &smcd_gid, &matches);
        }
        mutex_unlock(&smcd_dev_list.mutex);
 
@@ -2194,7 +2233,8 @@ static void smc_find_ism_v1_device_serv(struct smc_sock *new_smc,
        if (!(ini->smcd_version & SMC_V1) || !smcd_indicated(ini->smc_type_v1))
                goto not_found;
        ini->is_smcd = true; /* prepare ISM check */
-       ini->ism_peer_gid[0] = ntohll(pclc_smcd->ism.gid);
+       ini->ism_peer_gid[0].gid = ntohll(pclc_smcd->ism.gid);
+       ini->ism_peer_gid[0].gid_ext = 0;
        rc = smc_find_ism_device(new_smc, ini);
        if (rc)
                goto not_found;
index 0dc722b..df64efd 100644 (file)
@@ -29,9 +29,6 @@
 #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
-                                        */
 #define SMC_AUTOCORKING_DEFAULT_SIZE   0x10000 /* 64K by default */
 
 extern struct proto smc_proto;
index 900d307..b43be3c 100644 (file)
@@ -883,11 +883,13 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
                       ETH_ALEN);
        }
        if (smcd_indicated(ini->smc_type_v1)) {
+               struct smcd_gid smcd_gid;
+
                /* add SMC-D specifics */
                if (ini->ism_dev[0]) {
                        smcd = ini->ism_dev[0];
-                       pclc_smcd->ism.gid =
-                               htonll(smcd->ops->get_local_gid(smcd));
+                       smcd->ops->get_local_gid(smcd, &smcd_gid);
+                       pclc_smcd->ism.gid = htonll(smcd_gid.gid);
                        pclc_smcd->ism.chid =
                                htons(smc_ism_get_chid(ini->ism_dev[0]));
                }
@@ -920,10 +922,11 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
                read_unlock(&smc_clc_eid_table.lock);
        }
        if (smcd_indicated(ini->smc_type_v2)) {
+               struct smcd_gid smcd_gid;
                u8 *eid = NULL;
+               int entry = 0;
 
                v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled;
-               v2_ext->hdr.ism_gid_cnt = ini->ism_offered_cnt;
                v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) -
                                offsetofend(struct smc_clnt_opts_area_hdr,
                                            smcd_v2_ext_offset) +
@@ -935,14 +938,26 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
                if (ini->ism_offered_cnt) {
                        for (i = 1; i <= ini->ism_offered_cnt; i++) {
                                smcd = ini->ism_dev[i];
-                               gidchids[i - 1].gid =
-                                       htonll(smcd->ops->get_local_gid(smcd));
-                               gidchids[i - 1].chid =
+                               smcd->ops->get_local_gid(smcd, &smcd_gid);
+                               gidchids[entry].chid =
                                        htons(smc_ism_get_chid(ini->ism_dev[i]));
+                               gidchids[entry].gid = htonll(smcd_gid.gid);
+                               if (smc_ism_is_virtual(smcd)) {
+                                       /* a virtual ISM device takes two
+                                        * entries. CHID of the second entry
+                                        * repeats that of the first entry.
+                                        */
+                                       gidchids[entry + 1].chid =
+                                               gidchids[entry].chid;
+                                       gidchids[entry + 1].gid =
+                                               htonll(smcd_gid.gid_ext);
+                                       entry++;
+                               }
+                               entry++;
                        }
-                       plen += ini->ism_offered_cnt *
-                               sizeof(struct smc_clc_smcd_gid_chid);
+                       plen += entry * sizeof(struct smc_clc_smcd_gid_chid);
                }
+               v2_ext->hdr.ism_gid_cnt = entry;
        }
        if (smcr_indicated(ini->smc_type_v2)) {
                memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE);
@@ -978,7 +993,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
                        vec[i++].iov_len = sizeof(*smcd_v2_ext);
                        if (ini->ism_offered_cnt) {
                                vec[i].iov_base = gidchids;
-                               vec[i++].iov_len = ini->ism_offered_cnt *
+                               vec[i++].iov_len = v2_ext->hdr.ism_gid_cnt *
                                        sizeof(struct smc_clc_smcd_gid_chid);
                        }
                }
@@ -1009,13 +1024,16 @@ smcd_clc_prep_confirm_accept(struct smc_connection *conn,
                             struct smc_clc_msg_trail *trl)
 {
        struct smcd_dev *smcd = conn->lgr->smcd;
+       struct smcd_gid smcd_gid;
+       u16 chid;
        int len;
 
        /* SMC-D specific settings */
        memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
               sizeof(SMCD_EYECATCHER));
+       smcd->ops->get_local_gid(smcd, &smcd_gid);
        clc->hdr.typev1 = SMC_TYPE_D;
-       clc->d0.gid = htonll(smcd->ops->get_local_gid(smcd));
+       clc->d0.gid = htonll(smcd_gid.gid);
        clc->d0.token = htonll(conn->rmb_desc->token);
        clc->d0.dmbe_size = conn->rmbe_size_comp;
        clc->d0.dmbe_idx = 0;
@@ -1023,9 +1041,12 @@ smcd_clc_prep_confirm_accept(struct smc_connection *conn,
        if (version == SMC_V1) {
                clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
        } else {
-               clc->d1.chid = htons(smc_ism_get_chid(smcd));
+               chid = smc_ism_get_chid(smcd);
+               clc->d1.chid = htons(chid);
                if (eid && eid[0])
                        memcpy(clc->d1.eid, eid, SMC_MAX_EID_LEN);
+               if (__smc_ism_is_virtual(chid))
+                       clc->d1.gid_ext = htonll(smcd_gid.gid_ext);
                len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2;
                if (first_contact) {
                        *fce_len = smc_clc_fill_fce_v2x(fce_v2x, ini);
index c187d5f..a9f9bdd 100644 (file)
@@ -172,6 +172,11 @@ struct smc_clc_msg_proposal {      /* clc proposal message sent by Linux */
 
 #define SMC_CLC_MAX_V6_PREFIX          8
 #define SMC_CLC_MAX_UEID               8
+#define SMCD_CLC_MAX_V2_GID_ENTRIES    8 /* max # of CHID-GID entries in CLC
+                                          * proposal SMC-Dv2 extension.
+                                          * each ISM device takes one entry and
+                                          * each virtual ISM takes two entries.
+                                          */
 
 struct smc_clc_msg_proposal_area {
        struct smc_clc_msg_proposal             pclc_base;
@@ -181,7 +186,8 @@ struct smc_clc_msg_proposal_area {
        struct smc_clc_v2_extension             pclc_v2_ext;
        u8                      user_eids[SMC_CLC_MAX_UEID][SMC_MAX_EID_LEN];
        struct smc_clc_smcd_v2_extension        pclc_smcd_v2_ext;
-       struct smc_clc_smcd_gid_chid            pclc_gidchids[SMC_MAX_ISM_DEVS];
+       struct smc_clc_smcd_gid_chid
+                               pclc_gidchids[SMCD_CLC_MAX_V2_GID_ENTRIES];
        struct smc_clc_msg_trail                pclc_trl;
 };
 
@@ -277,7 +283,7 @@ struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */
                        struct { /* v2 only, but 12 bytes reserved in v1 */
                                __be16 chid;
                                u8 eid[SMC_MAX_EID_LEN];
-                               u8 reserved5[8];
+                               __be64 gid_ext;
                        } __packed d1;
                };
        };
index d520ee6..672eff0 100644 (file)
@@ -506,6 +506,7 @@ static int smc_nl_fill_smcd_lgr(struct smc_link_group *lgr,
 {
        char smc_pnet[SMC_MAX_PNETID_LEN + 1];
        struct smcd_dev *smcd = lgr->smcd;
+       struct smcd_gid smcd_gid;
        struct nlattr *attrs;
        void *nlh;
 
@@ -521,11 +522,11 @@ static int smc_nl_fill_smcd_lgr(struct smc_link_group *lgr,
 
        if (nla_put_u32(skb, SMC_NLA_LGR_D_ID, *((u32 *)&lgr->id)))
                goto errattr;
+       smcd->ops->get_local_gid(smcd, &smcd_gid);
        if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_GID,
-                             smcd->ops->get_local_gid(smcd),
-                                 SMC_NLA_LGR_D_PAD))
+                             smcd_gid.gid, SMC_NLA_LGR_D_PAD))
                goto errattr;
-       if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_PEER_GID, lgr->peer_gid,
+       if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_PEER_GID, lgr->peer_gid.gid,
                              SMC_NLA_LGR_D_PAD))
                goto errattr;
        if (nla_put_u8(skb, SMC_NLA_LGR_D_VLAN_ID, lgr->vlan_id))
@@ -876,7 +877,10 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
                /* SMC-D specific settings */
                smcd = ini->ism_dev[ini->ism_selected];
                get_device(smcd->ops->get_dev(smcd));
-               lgr->peer_gid = ini->ism_peer_gid[ini->ism_selected];
+               lgr->peer_gid.gid =
+                       ini->ism_peer_gid[ini->ism_selected].gid;
+               lgr->peer_gid.gid_ext =
+                       ini->ism_peer_gid[ini->ism_selected].gid_ext;
                lgr->smcd = ini->ism_dev[ini->ism_selected];
                lgr_list = &ini->ism_dev[ini->ism_selected]->lgr_list;
                lgr_lock = &lgr->smcd->lgr_lock;
@@ -1514,7 +1518,8 @@ void smc_lgr_terminate_sched(struct smc_link_group *lgr)
 }
 
 /* Called when peer lgr shutdown (regularly or abnormally) is received */
-void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
+void smc_smcd_terminate(struct smcd_dev *dev, struct smcd_gid *peer_gid,
+                       unsigned short vlan)
 {
        struct smc_link_group *lgr, *l;
        LIST_HEAD(lgr_free_list);
@@ -1522,9 +1527,12 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
        /* run common cleanup function and build free list */
        spin_lock_bh(&dev->lgr_lock);
        list_for_each_entry_safe(lgr, l, &dev->lgr_list, list) {
-               if ((!peer_gid || lgr->peer_gid == peer_gid) &&
+               if ((!peer_gid->gid ||
+                    (lgr->peer_gid.gid == peer_gid->gid &&
+                     !smc_ism_is_virtual(dev) ? 1 :
+                     lgr->peer_gid.gid_ext == peer_gid->gid_ext)) &&
                    (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
-                       if (peer_gid) /* peer triggered termination */
+                       if (peer_gid->gid) /* peer triggered termination */
                                lgr->peer_shutdown = 1;
                        list_move(&lgr->list, &lgr_free_list);
                        lgr->freeing = 1;
@@ -1860,9 +1868,12 @@ static bool smcr_lgr_match(struct smc_link_group *lgr, u8 smcr_version,
 }
 
 static bool smcd_lgr_match(struct smc_link_group *lgr,
-                          struct smcd_dev *smcismdev, u64 peer_gid)
+                          struct smcd_dev *smcismdev,
+                          struct smcd_gid *peer_gid)
 {
-       return lgr->peer_gid == peer_gid && lgr->smcd == smcismdev;
+       return lgr->peer_gid.gid == peer_gid->gid && lgr->smcd == smcismdev &&
+               smc_ism_is_virtual(smcismdev) ?
+               (lgr->peer_gid.gid_ext == peer_gid->gid_ext) : 1;
 }
 
 /* create a new SMC connection (and a new link group if necessary) */
@@ -1892,7 +1903,7 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
                write_lock_bh(&lgr->conns_lock);
                if ((ini->is_smcd ?
                     smcd_lgr_match(lgr, ini->ism_dev[ini->ism_selected],
-                                   ini->ism_peer_gid[ini->ism_selected]) :
+                                   &ini->ism_peer_gid[ini->ism_selected]) :
                     smcr_lgr_match(lgr, ini->smcr_version,
                                    ini->peer_systemid,
                                    ini->peer_gid, ini->peer_mac, role,
index 9f65678..1f17537 100644 (file)
 #include <linux/pci.h>
 #include <rdma/ib_verbs.h>
 #include <net/genetlink.h>
+#include <net/smc.h>
 
 #include "smc.h"
 #include "smc_ib.h"
+#include "smc_clc.h"
 
 #define SMC_RMBS_PER_LGR_MAX   255     /* max. # of RMBs per link group */
 #define SMC_CONN_PER_LGR_MIN   16      /* min. # of connections per link group */
@@ -355,7 +357,7 @@ struct smc_link_group {
                                                /* max links can be added in lgr */
                };
                struct { /* SMC-D */
-                       u64                     peer_gid;
+                       struct smcd_gid         peer_gid;
                                                /* Peer GID (remote) */
                        struct smcd_dev         *smcd;
                                                /* ISM device for VLAN reg. */
@@ -392,6 +394,11 @@ struct smc_init_info_smcrv2 {
        struct smc_gidlist      gidlist;
 };
 
+#define SMC_MAX_V2_ISM_DEVS    SMCD_CLC_MAX_V2_GID_ENTRIES
+                               /* max # of proposed non-native ISM devices,
+                                * which can't exceed the max # of CHID-GID
+                                * entries in CLC proposal SMC-Dv2 extension.
+                                */
 struct smc_init_info {
        u8                      is_smcd;
        u8                      smc_type_v1;
@@ -417,9 +424,9 @@ struct smc_init_info {
        u32                     ib_clcqpn;
        struct smc_init_info_smcrv2 smcrv2;
        /* SMC-D */
-       u64                     ism_peer_gid[SMC_MAX_ISM_DEVS + 1];
-       struct smcd_dev         *ism_dev[SMC_MAX_ISM_DEVS + 1];
-       u16                     ism_chid[SMC_MAX_ISM_DEVS + 1];
+       struct smcd_gid         ism_peer_gid[SMC_MAX_V2_ISM_DEVS + 1];
+       struct smcd_dev         *ism_dev[SMC_MAX_V2_ISM_DEVS + 1];
+       u16                     ism_chid[SMC_MAX_V2_ISM_DEVS + 1];
        u8                      ism_offered_cnt; /* # of ISM devices offered */
        u8                      ism_selected;    /* index of selected ISM dev*/
        u8                      smcd_version;
@@ -545,7 +552,7 @@ void smc_lgr_hold(struct smc_link_group *lgr);
 void smc_lgr_put(struct smc_link_group *lgr);
 void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport);
 void smcr_port_err(struct smc_ib_device *smcibdev, u8 ibport);
-void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid,
+void smc_smcd_terminate(struct smcd_dev *dev, struct smcd_gid *peer_gid,
                        unsigned short vlan);
 void smc_smcd_terminate_all(struct smcd_dev *dev);
 void smc_smcr_terminate_all(struct smc_ib_device *smcibdev);
index a584613..c180c18 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "smc.h"
 #include "smc_core.h"
+#include "smc_ism.h"
 
 struct smc_diag_dump_ctx {
        int pos[2];
@@ -168,12 +169,14 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
                struct smc_connection *conn = &smc->conn;
                struct smcd_diag_dmbinfo dinfo;
                struct smcd_dev *smcd = conn->lgr->smcd;
+               struct smcd_gid smcd_gid;
 
                memset(&dinfo, 0, sizeof(dinfo));
 
                dinfo.linkid = *((u32 *)conn->lgr->id);
-               dinfo.peer_gid = conn->lgr->peer_gid;
-               dinfo.my_gid = smcd->ops->get_local_gid(smcd);
+               dinfo.peer_gid = conn->lgr->peer_gid.gid;
+               smcd->ops->get_local_gid(smcd, &smcd_gid);
+               dinfo.my_gid = smcd_gid.gid;
                dinfo.token = conn->rmb_desc->token;
                dinfo.peer_token = conn->peer_token;
 
index fbee249..a33f861 100644 (file)
@@ -44,7 +44,8 @@ static struct ism_client smc_ism_client = {
 #endif
 
 /* Test if an ISM communication is possible - same CPC */
-int smc_ism_cantalk(u64 peer_gid, unsigned short vlan_id, struct smcd_dev *smcd)
+int smc_ism_cantalk(struct smcd_gid *peer_gid, unsigned short vlan_id,
+                   struct smcd_dev *smcd)
 {
        return smcd->ops->query_remote_gid(smcd, peer_gid, vlan_id ? 1 : 0,
                                           vlan_id);
@@ -208,7 +209,7 @@ int smc_ism_register_dmb(struct smc_link_group *lgr, int dmb_len,
        dmb.dmb_len = dmb_len;
        dmb.sba_idx = dmb_desc->sba_idx;
        dmb.vlan_id = lgr->vlan_id;
-       dmb.rgid = lgr->peer_gid;
+       dmb.rgid = lgr->peer_gid.gid;
        rc = lgr->smcd->ops->register_dmb(lgr->smcd, &dmb, &smc_ism_client);
        if (!rc) {
                dmb_desc->sba_idx = dmb.sba_idx;
@@ -340,18 +341,20 @@ union smcd_sw_event_info {
 
 static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
 {
+       struct smcd_gid peer_gid = { .gid = wrk->event.tok,
+                                    .gid_ext = 0 };
        union smcd_sw_event_info ev_info;
 
        ev_info.info = wrk->event.info;
        switch (wrk->event.code) {
        case ISM_EVENT_CODE_SHUTDOWN:   /* Peer shut down DMBs */
-               smc_smcd_terminate(wrk->smcd, wrk->event.tok, ev_info.vlan_id);
+               smc_smcd_terminate(wrk->smcd, &peer_gid, ev_info.vlan_id);
                break;
        case ISM_EVENT_CODE_TESTLINK:   /* Activity timer */
                if (ev_info.code == ISM_EVENT_REQUEST) {
                        ev_info.code = ISM_EVENT_RESPONSE;
                        wrk->smcd->ops->signal_event(wrk->smcd,
-                                                    wrk->event.tok,
+                                                    &peer_gid,
                                                     ISM_EVENT_REQUEST_IR,
                                                     ISM_EVENT_CODE_TESTLINK,
                                                     ev_info.info);
@@ -365,10 +368,12 @@ static void smc_ism_event_work(struct work_struct *work)
 {
        struct smc_ism_event_work *wrk =
                container_of(work, struct smc_ism_event_work, work);
+       struct smcd_gid smcd_gid = { .gid = wrk->event.tok,
+                                    .gid_ext = 0 };
 
        switch (wrk->event.type) {
        case ISM_EVENT_GID:     /* GID event, token is peer GID */
-               smc_smcd_terminate(wrk->smcd, wrk->event.tok, VLAN_VID_MASK);
+               smc_smcd_terminate(wrk->smcd, &smcd_gid, VLAN_VID_MASK);
                break;
        case ISM_EVENT_DMB:
                break;
@@ -525,7 +530,7 @@ int smc_ism_signal_shutdown(struct smc_link_group *lgr)
        memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
        ev_info.vlan_id = lgr->vlan_id;
        ev_info.code = ISM_EVENT_REQUEST;
-       rc = lgr->smcd->ops->signal_event(lgr->smcd, lgr->peer_gid,
+       rc = lgr->smcd->ops->signal_event(lgr->smcd, &lgr->peer_gid,
                                          ISM_EVENT_REQUEST_IR,
                                          ISM_EVENT_CODE_SHUTDOWN,
                                          ev_info.info);
index d1228a6..0e5e563 100644 (file)
@@ -32,7 +32,8 @@ struct smc_ism_vlanid {                       /* VLAN id set on ISM device */
 
 struct smcd_dev;
 
-int smc_ism_cantalk(u64 peer_gid, unsigned short vlan_id, struct smcd_dev *dev);
+int smc_ism_cantalk(struct smcd_gid *peer_gid, unsigned short vlan_id,
+                   struct smcd_dev *dev);
 void smc_ism_set_conn(struct smc_connection *conn);
 void smc_ism_unset_conn(struct smc_connection *conn);
 int smc_ism_get_vlan(struct smcd_dev *dev, unsigned short vlan_id);
index 1177540..9f2c58c 100644 (file)
@@ -1103,8 +1103,8 @@ 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[0] ||
-                    !smc_ism_cantalk(ini->ism_peer_gid[0], ini->vlan_id,
+                   (!ini->ism_peer_gid[0].gid ||
+                    !smc_ism_cantalk(&ini->ism_peer_gid[0], ini->vlan_id,
                                      ismdev))) {
                        ini->ism_dev[0] = ismdev;
                        break;