net/smc: compatible with 128-bits extended GID of virtual ISM device

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>
This commit is contained in:
Wen Gu 2023-12-19 22:26:13 +08:00 committed by David S. Miller
parent 8dd512df3c
commit b40584d145
12 changed files with 167 additions and 68 deletions

View File

@ -743,10 +743,10 @@ static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid,
return ism_cmd(ism, &cmd); return ism_cmd(ism, &cmd);
} }
static int smcd_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid, static int smcd_query_rgid(struct smcd_dev *smcd, struct smcd_gid *rgid,
u32 vid) 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, 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); return ism_cmd(ism, &cmd);
} }
static int smcd_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq, static int smcd_signal_ieq(struct smcd_dev *smcd, struct smcd_gid *rgid,
u32 event_code, u64 info) 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, 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; 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) static u16 ism_get_chid(struct ism_dev *ism)

View File

@ -52,9 +52,14 @@ struct smcd_dmb {
struct smcd_dev; struct smcd_dev;
struct ism_client; struct ism_client;
struct smcd_gid {
u64 gid;
u64 gid_ext;
};
struct smcd_ops { struct smcd_ops {
int (*query_remote_gid)(struct smcd_dev *dev, u64 rgid, u32 vid_valid, int (*query_remote_gid)(struct smcd_dev *dev, struct smcd_gid *rgid,
u32 vid); u32 vid_valid, u32 vid);
int (*register_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb, int (*register_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb,
struct ism_client *client); struct ism_client *client);
int (*unregister_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb); 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 (*del_vlan_id)(struct smcd_dev *dev, u64 vlan_id);
int (*set_vlan_required)(struct smcd_dev *dev); int (*set_vlan_required)(struct smcd_dev *dev);
int (*reset_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, int (*signal_event)(struct smcd_dev *dev, struct smcd_gid *rgid,
u32 event_code, u64 info); u32 trigger_irq, u32 event_code, u64 info);
int (*move_data)(struct smcd_dev *dev, u64 dmb_tok, unsigned int idx, int (*move_data)(struct smcd_dev *dev, u64 dmb_tok, unsigned int idx,
bool sf, unsigned int offset, void *data, bool sf, unsigned int offset, void *data,
unsigned int size); unsigned int size);
int (*supports_v2)(void); int (*supports_v2)(void);
u8* (*get_system_eid)(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); u16 (*get_chid)(struct smcd_dev *dev);
struct device* (*get_dev)(struct smcd_dev *dev); struct device* (*get_dev)(struct smcd_dev *dev);
}; };

View File

@ -1044,7 +1044,8 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
{ {
int rc = SMC_CLC_DECL_NOSMCDDEV; int rc = SMC_CLC_DECL_NOSMCDDEV;
struct smcd_dev *smcd; struct smcd_dev *smcd;
int i = 1; int i = 1, entry = 1;
bool is_virtual;
u16 chid; u16 chid;
if (smcd_indicated(ini->smc_type_v1)) 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); chid = smc_ism_get_chid(smcd);
if (!smc_find_ism_v2_is_unique_chid(chid, ini, i)) if (!smc_find_ism_v2_is_unique_chid(chid, ini, i))
continue; continue;
is_virtual = __smc_ism_is_virtual(chid);
if (!smc_pnet_is_pnetid_set(smcd->pnetid) || if (!smc_pnet_is_pnetid_set(smcd->pnetid) ||
smc_pnet_is_ndev_pnetid(sock_net(&smc->sk), 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_dev[i] = smcd;
ini->ism_chid[i] = chid; ini->ism_chid[i] = chid;
ini->is_smcd = true; ini->is_smcd = true;
rc = 0; rc = 0;
i++; i++;
if (i > SMC_MAX_ISM_DEVS) entry = is_virtual ? entry + 2 : entry + 1;
if (entry > SMCD_CLC_MAX_V2_GID_ENTRIES)
break; break;
} }
} }
@ -1402,8 +1412,13 @@ static int smc_connect_ism(struct smc_sock *smc,
rc = smc_v2_determine_accepted_chid(aclc, ini); rc = smc_v2_determine_accepted_chid(aclc, ini);
if (rc) if (rc)
return 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 */ /* there is only one lgr role for SMC-D; use server lock */
mutex_lock(&smc_server_lgr_pending); 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 */ /* check for ISM devices matching proposed ISM devices */
static void smc_check_ism_v2_match(struct smc_init_info *ini, 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) unsigned int *matches)
{ {
struct smcd_dev *smcd; struct smcd_dev *smcd;
@ -2100,7 +2116,11 @@ static void smc_check_ism_v2_match(struct smc_init_info *ini,
continue; continue;
if (smc_ism_get_chid(smcd) == proposed_chid && if (smc_ism_get_chid(smcd) == proposed_chid &&
!smc_ism_cantalk(proposed_gid, ISM_RESERVED_VLANID, smcd)) { !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; ini->ism_dev[*matches] = smcd;
(*matches)++; (*matches)++;
break; 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_v2_extension *smc_v2_ext;
struct smc_clc_msg_smcd *pclc_smcd; struct smc_clc_msg_smcd *pclc_smcd;
unsigned int matches = 0; unsigned int matches = 0;
struct smcd_gid smcd_gid;
u8 smcd_version; u8 smcd_version;
u8 *eid = NULL; u8 *eid = NULL;
int i, rc; int i, rc;
u16 chid;
if (!(ini->smcd_version & SMC_V2) || !smcd_indicated(ini->smc_type_v2)) if (!(ini->smcd_version & SMC_V2) || !smcd_indicated(ini->smc_type_v2))
goto not_found; 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); smcd_v2_ext = smc_get_clc_smcd_v2_ext(smc_v2_ext);
mutex_lock(&smcd_dev_list.mutex); 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 */ /* 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), smc_check_ism_v2_match(ini, ntohs(pclc_smcd->ism.chid),
ntohll(pclc_smcd->ism.gid), &matches); &smcd_gid, &matches);
for (i = 1; i <= smc_v2_ext->hdr.ism_gid_cnt; i++) { }
for (i = 0; i < smc_v2_ext->hdr.ism_gid_cnt; i++) {
/* check for ISM devices matching proposed non-native ISM /* check for ISM devices matching proposed non-native ISM
* devices * devices
*/ */
smc_check_ism_v2_match(ini, smcd_gid.gid = ntohll(smcd_v2_ext->gidchid[i].gid);
ntohs(smcd_v2_ext->gidchid[i - 1].chid), smcd_gid.gid_ext = 0;
ntohll(smcd_v2_ext->gidchid[i - 1].gid), chid = ntohs(smcd_v2_ext->gidchid[i].chid);
&matches); 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); 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)) if (!(ini->smcd_version & SMC_V1) || !smcd_indicated(ini->smc_type_v1))
goto not_found; goto not_found;
ini->is_smcd = true; /* prepare ISM check */ 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); rc = smc_find_ism_device(new_smc, ini);
if (rc) if (rc)
goto not_found; goto not_found;

View File

@ -29,9 +29,6 @@
#define SMCPROTO_SMC 0 /* SMC protocol, IPv4 */ #define SMCPROTO_SMC 0 /* SMC protocol, IPv4 */
#define SMCPROTO_SMC6 1 /* SMC protocol, IPv6 */ #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 */ #define SMC_AUTOCORKING_DEFAULT_SIZE 0x10000 /* 64K by default */
extern struct proto smc_proto; extern struct proto smc_proto;

View File

@ -883,11 +883,13 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
ETH_ALEN); ETH_ALEN);
} }
if (smcd_indicated(ini->smc_type_v1)) { if (smcd_indicated(ini->smc_type_v1)) {
struct smcd_gid smcd_gid;
/* add SMC-D specifics */ /* add SMC-D specifics */
if (ini->ism_dev[0]) { if (ini->ism_dev[0]) {
smcd = ini->ism_dev[0]; smcd = ini->ism_dev[0];
pclc_smcd->ism.gid = smcd->ops->get_local_gid(smcd, &smcd_gid);
htonll(smcd->ops->get_local_gid(smcd)); pclc_smcd->ism.gid = htonll(smcd_gid.gid);
pclc_smcd->ism.chid = pclc_smcd->ism.chid =
htons(smc_ism_get_chid(ini->ism_dev[0])); 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); read_unlock(&smc_clc_eid_table.lock);
} }
if (smcd_indicated(ini->smc_type_v2)) { if (smcd_indicated(ini->smc_type_v2)) {
struct smcd_gid smcd_gid;
u8 *eid = NULL; u8 *eid = NULL;
int entry = 0;
v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled; 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) - v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) -
offsetofend(struct smc_clnt_opts_area_hdr, offsetofend(struct smc_clnt_opts_area_hdr,
smcd_v2_ext_offset) + 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) { if (ini->ism_offered_cnt) {
for (i = 1; i <= ini->ism_offered_cnt; i++) { for (i = 1; i <= ini->ism_offered_cnt; i++) {
smcd = ini->ism_dev[i]; smcd = ini->ism_dev[i];
gidchids[i - 1].gid = smcd->ops->get_local_gid(smcd, &smcd_gid);
htonll(smcd->ops->get_local_gid(smcd)); gidchids[entry].chid =
gidchids[i - 1].chid =
htons(smc_ism_get_chid(ini->ism_dev[i])); 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 * plen += entry * sizeof(struct smc_clc_smcd_gid_chid);
sizeof(struct smc_clc_smcd_gid_chid);
} }
v2_ext->hdr.ism_gid_cnt = entry;
} }
if (smcr_indicated(ini->smc_type_v2)) { if (smcr_indicated(ini->smc_type_v2)) {
memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE); 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); vec[i++].iov_len = sizeof(*smcd_v2_ext);
if (ini->ism_offered_cnt) { if (ini->ism_offered_cnt) {
vec[i].iov_base = gidchids; 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); 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 smc_clc_msg_trail *trl)
{ {
struct smcd_dev *smcd = conn->lgr->smcd; struct smcd_dev *smcd = conn->lgr->smcd;
struct smcd_gid smcd_gid;
u16 chid;
int len; int len;
/* SMC-D specific settings */ /* SMC-D specific settings */
memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER, memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
sizeof(SMCD_EYECATCHER)); sizeof(SMCD_EYECATCHER));
smcd->ops->get_local_gid(smcd, &smcd_gid);
clc->hdr.typev1 = SMC_TYPE_D; 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.token = htonll(conn->rmb_desc->token);
clc->d0.dmbe_size = conn->rmbe_size_comp; clc->d0.dmbe_size = conn->rmbe_size_comp;
clc->d0.dmbe_idx = 0; clc->d0.dmbe_idx = 0;
@ -1023,9 +1041,12 @@ smcd_clc_prep_confirm_accept(struct smc_connection *conn,
if (version == SMC_V1) { if (version == SMC_V1) {
clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN); clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
} else { } 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]) if (eid && eid[0])
memcpy(clc->d1.eid, eid, SMC_MAX_EID_LEN); 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; len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2;
if (first_contact) { if (first_contact) {
*fce_len = smc_clc_fill_fce_v2x(fce_v2x, ini); *fce_len = smc_clc_fill_fce_v2x(fce_v2x, ini);

View 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_V6_PREFIX 8
#define SMC_CLC_MAX_UEID 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_area {
struct smc_clc_msg_proposal pclc_base; 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; struct smc_clc_v2_extension pclc_v2_ext;
u8 user_eids[SMC_CLC_MAX_UEID][SMC_MAX_EID_LEN]; 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_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; 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 */ struct { /* v2 only, but 12 bytes reserved in v1 */
__be16 chid; __be16 chid;
u8 eid[SMC_MAX_EID_LEN]; u8 eid[SMC_MAX_EID_LEN];
u8 reserved5[8]; __be64 gid_ext;
} __packed d1; } __packed d1;
}; };
}; };

View 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]; char smc_pnet[SMC_MAX_PNETID_LEN + 1];
struct smcd_dev *smcd = lgr->smcd; struct smcd_dev *smcd = lgr->smcd;
struct smcd_gid smcd_gid;
struct nlattr *attrs; struct nlattr *attrs;
void *nlh; 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))) if (nla_put_u32(skb, SMC_NLA_LGR_D_ID, *((u32 *)&lgr->id)))
goto errattr; goto errattr;
smcd->ops->get_local_gid(smcd, &smcd_gid);
if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_GID, if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_GID,
smcd->ops->get_local_gid(smcd), smcd_gid.gid, SMC_NLA_LGR_D_PAD))
SMC_NLA_LGR_D_PAD))
goto errattr; 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)) SMC_NLA_LGR_D_PAD))
goto errattr; goto errattr;
if (nla_put_u8(skb, SMC_NLA_LGR_D_VLAN_ID, lgr->vlan_id)) 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 */ /* SMC-D specific settings */
smcd = ini->ism_dev[ini->ism_selected]; smcd = ini->ism_dev[ini->ism_selected];
get_device(smcd->ops->get_dev(smcd)); 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->smcd = ini->ism_dev[ini->ism_selected];
lgr_list = &ini->ism_dev[ini->ism_selected]->lgr_list; lgr_list = &ini->ism_dev[ini->ism_selected]->lgr_list;
lgr_lock = &lgr->smcd->lgr_lock; 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 */ /* 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; struct smc_link_group *lgr, *l;
LIST_HEAD(lgr_free_list); 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 */ /* run common cleanup function and build free list */
spin_lock_bh(&dev->lgr_lock); spin_lock_bh(&dev->lgr_lock);
list_for_each_entry_safe(lgr, l, &dev->lgr_list, list) { 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)) { (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; lgr->peer_shutdown = 1;
list_move(&lgr->list, &lgr_free_list); list_move(&lgr->list, &lgr_free_list);
lgr->freeing = 1; 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, 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) */ /* 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); write_lock_bh(&lgr->conns_lock);
if ((ini->is_smcd ? if ((ini->is_smcd ?
smcd_lgr_match(lgr, ini->ism_dev[ini->ism_selected], 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, smcr_lgr_match(lgr, ini->smcr_version,
ini->peer_systemid, ini->peer_systemid,
ini->peer_gid, ini->peer_mac, role, ini->peer_gid, ini->peer_mac, role,

View File

@ -17,9 +17,11 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
#include <net/genetlink.h> #include <net/genetlink.h>
#include <net/smc.h>
#include "smc.h" #include "smc.h"
#include "smc_ib.h" #include "smc_ib.h"
#include "smc_clc.h"
#define SMC_RMBS_PER_LGR_MAX 255 /* max. # of RMBs per link group */ #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 */ #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 */ /* max links can be added in lgr */
}; };
struct { /* SMC-D */ struct { /* SMC-D */
u64 peer_gid; struct smcd_gid peer_gid;
/* Peer GID (remote) */ /* Peer GID (remote) */
struct smcd_dev *smcd; struct smcd_dev *smcd;
/* ISM device for VLAN reg. */ /* ISM device for VLAN reg. */
@ -392,6 +394,11 @@ struct smc_init_info_smcrv2 {
struct smc_gidlist gidlist; 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 { struct smc_init_info {
u8 is_smcd; u8 is_smcd;
u8 smc_type_v1; u8 smc_type_v1;
@ -417,9 +424,9 @@ struct smc_init_info {
u32 ib_clcqpn; u32 ib_clcqpn;
struct smc_init_info_smcrv2 smcrv2; struct smc_init_info_smcrv2 smcrv2;
/* SMC-D */ /* SMC-D */
u64 ism_peer_gid[SMC_MAX_ISM_DEVS + 1]; struct smcd_gid ism_peer_gid[SMC_MAX_V2_ISM_DEVS + 1];
struct smcd_dev *ism_dev[SMC_MAX_ISM_DEVS + 1]; struct smcd_dev *ism_dev[SMC_MAX_V2_ISM_DEVS + 1];
u16 ism_chid[SMC_MAX_ISM_DEVS + 1]; u16 ism_chid[SMC_MAX_V2_ISM_DEVS + 1];
u8 ism_offered_cnt; /* # of ISM devices offered */ u8 ism_offered_cnt; /* # of ISM devices offered */
u8 ism_selected; /* index of selected ISM dev*/ u8 ism_selected; /* index of selected ISM dev*/
u8 smcd_version; 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 smc_lgr_put(struct smc_link_group *lgr);
void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport); void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport);
void smcr_port_err(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); unsigned short vlan);
void smc_smcd_terminate_all(struct smcd_dev *dev); void smc_smcd_terminate_all(struct smcd_dev *dev);
void smc_smcr_terminate_all(struct smc_ib_device *smcibdev); void smc_smcr_terminate_all(struct smc_ib_device *smcibdev);

View File

@ -21,6 +21,7 @@
#include "smc.h" #include "smc.h"
#include "smc_core.h" #include "smc_core.h"
#include "smc_ism.h"
struct smc_diag_dump_ctx { struct smc_diag_dump_ctx {
int pos[2]; 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 smc_connection *conn = &smc->conn;
struct smcd_diag_dmbinfo dinfo; struct smcd_diag_dmbinfo dinfo;
struct smcd_dev *smcd = conn->lgr->smcd; struct smcd_dev *smcd = conn->lgr->smcd;
struct smcd_gid smcd_gid;
memset(&dinfo, 0, sizeof(dinfo)); memset(&dinfo, 0, sizeof(dinfo));
dinfo.linkid = *((u32 *)conn->lgr->id); dinfo.linkid = *((u32 *)conn->lgr->id);
dinfo.peer_gid = conn->lgr->peer_gid; dinfo.peer_gid = conn->lgr->peer_gid.gid;
dinfo.my_gid = smcd->ops->get_local_gid(smcd); smcd->ops->get_local_gid(smcd, &smcd_gid);
dinfo.my_gid = smcd_gid.gid;
dinfo.token = conn->rmb_desc->token; dinfo.token = conn->rmb_desc->token;
dinfo.peer_token = conn->peer_token; dinfo.peer_token = conn->peer_token;

View File

@ -44,7 +44,8 @@ static struct ism_client smc_ism_client = {
#endif #endif
/* Test if an ISM communication is possible - same CPC */ /* 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, return smcd->ops->query_remote_gid(smcd, peer_gid, vlan_id ? 1 : 0,
vlan_id); 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.dmb_len = dmb_len;
dmb.sba_idx = dmb_desc->sba_idx; dmb.sba_idx = dmb_desc->sba_idx;
dmb.vlan_id = lgr->vlan_id; 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); rc = lgr->smcd->ops->register_dmb(lgr->smcd, &dmb, &smc_ism_client);
if (!rc) { if (!rc) {
dmb_desc->sba_idx = dmb.sba_idx; 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) 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; union smcd_sw_event_info ev_info;
ev_info.info = wrk->event.info; ev_info.info = wrk->event.info;
switch (wrk->event.code) { switch (wrk->event.code) {
case ISM_EVENT_CODE_SHUTDOWN: /* Peer shut down DMBs */ 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; break;
case ISM_EVENT_CODE_TESTLINK: /* Activity timer */ case ISM_EVENT_CODE_TESTLINK: /* Activity timer */
if (ev_info.code == ISM_EVENT_REQUEST) { if (ev_info.code == ISM_EVENT_REQUEST) {
ev_info.code = ISM_EVENT_RESPONSE; ev_info.code = ISM_EVENT_RESPONSE;
wrk->smcd->ops->signal_event(wrk->smcd, wrk->smcd->ops->signal_event(wrk->smcd,
wrk->event.tok, &peer_gid,
ISM_EVENT_REQUEST_IR, ISM_EVENT_REQUEST_IR,
ISM_EVENT_CODE_TESTLINK, ISM_EVENT_CODE_TESTLINK,
ev_info.info); ev_info.info);
@ -365,10 +368,12 @@ static void smc_ism_event_work(struct work_struct *work)
{ {
struct smc_ism_event_work *wrk = struct smc_ism_event_work *wrk =
container_of(work, struct smc_ism_event_work, work); 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) { switch (wrk->event.type) {
case ISM_EVENT_GID: /* GID event, token is peer GID */ 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; break;
case ISM_EVENT_DMB: case ISM_EVENT_DMB:
break; 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); memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
ev_info.vlan_id = lgr->vlan_id; ev_info.vlan_id = lgr->vlan_id;
ev_info.code = ISM_EVENT_REQUEST; 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_REQUEST_IR,
ISM_EVENT_CODE_SHUTDOWN, ISM_EVENT_CODE_SHUTDOWN,
ev_info.info); ev_info.info);

View File

@ -32,7 +32,8 @@ struct smc_ism_vlanid { /* VLAN id set on ISM device */
struct smcd_dev; 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_set_conn(struct smc_connection *conn);
void smc_ism_unset_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); int smc_ism_get_vlan(struct smcd_dev *dev, unsigned short vlan_id);

View 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) { list_for_each_entry(ismdev, &smcd_dev_list.list, list) {
if (smc_pnet_match(ismdev->pnetid, ndev_pnetid) && if (smc_pnet_match(ismdev->pnetid, ndev_pnetid) &&
!ismdev->going_away && !ismdev->going_away &&
(!ini->ism_peer_gid[0] || (!ini->ism_peer_gid[0].gid ||
!smc_ism_cantalk(ini->ism_peer_gid[0], ini->vlan_id, !smc_ism_cantalk(&ini->ism_peer_gid[0], ini->vlan_id,
ismdev))) { ismdev))) {
ini->ism_dev[0] = ismdev; ini->ism_dev[0] = ismdev;
break; break;