Skip to content

Commit

Permalink
net/smc: compatible with 128-bits extended GID of virtual ISM device
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Wen Gu authored and David S. Miller committed Dec 26, 2023
1 parent 8dd512d commit b40584d
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 68 deletions.
19 changes: 11 additions & 8 deletions drivers/s390/net/ism_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down
15 changes: 10 additions & 5 deletions include/net/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,29 @@ 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);
int (*add_vlan_id)(struct smcd_dev *dev, u64 vlan_id);
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);
};
Expand Down
66 changes: 53 additions & 13 deletions net/smc/af_smc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand Down
3 changes: 0 additions & 3 deletions net/smc/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
43 changes: 32 additions & 11 deletions net/smc/smc_clc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]));
}
Expand Down Expand Up @@ -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) +
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -1009,23 +1024,29 @@ 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;
memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
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);
Expand Down
10 changes: 8 additions & 2 deletions net/smc/smc_clc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
};

Expand Down Expand Up @@ -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;
};
};
Expand Down
Loading

0 comments on commit b40584d

Please sign in to comment.