Commit 3fc64937 authored by Ursula Braun's avatar Ursula Braun Committed by David S. Miller

net/smc: prepare for more proposed ISM devices

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: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e15c6c46
...@@ -564,7 +564,7 @@ static int smc_find_ism_device(struct smc_sock *smc, struct smc_init_info *ini) ...@@ -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 */ /* Find ISM device with same PNETID as connecting interface */
smc_pnet_find_ism_resource(smc->clcsock->sk, ini); smc_pnet_find_ism_resource(smc->clcsock->sk, ini);
if (!ini->ism_dev) if (!ini->ism_dev[0])
return SMC_CLC_DECL_NOSMCDDEV; return SMC_CLC_DECL_NOSMCDDEV;
return 0; return 0;
} }
...@@ -573,7 +573,7 @@ static int smc_find_ism_device(struct smc_sock *smc, struct smc_init_info *ini) ...@@ -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, static int smc_connect_ism_vlan_setup(struct smc_sock *smc,
struct smc_init_info *ini) 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 SMC_CLC_DECL_ISMVLANERR;
return 0; return 0;
} }
...@@ -586,7 +586,7 @@ static int smc_connect_ism_vlan_cleanup(struct smc_sock *smc, bool is_smcd, ...@@ -586,7 +586,7 @@ static int smc_connect_ism_vlan_cleanup(struct smc_sock *smc, bool is_smcd,
{ {
if (!is_smcd) if (!is_smcd)
return 0; 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 SMC_CLC_DECL_CNFERR;
return 0; return 0;
} }
...@@ -712,7 +712,7 @@ static int smc_connect_ism(struct smc_sock *smc, ...@@ -712,7 +712,7 @@ static int smc_connect_ism(struct smc_sock *smc,
int rc = 0; int rc = 0;
ini->is_smcd = true; 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; ini->first_contact_peer = aclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK;
/* there is only one lgr role for SMC-D; use server lock */ /* there is only one lgr role for SMC-D; use server lock */
...@@ -754,7 +754,7 @@ static int __smc_connect(struct smc_sock *smc) ...@@ -754,7 +754,7 @@ static int __smc_connect(struct smc_sock *smc)
{ {
bool ism_supported = false, rdma_supported = false; bool ism_supported = false, rdma_supported = false;
struct smc_clc_msg_accept_confirm aclc; struct smc_clc_msg_accept_confirm aclc;
struct smc_init_info ini = {0}; struct smc_init_info *ini = NULL;
int smc_type; int smc_type;
int rc = 0; int rc = 0;
...@@ -769,21 +769,27 @@ static int __smc_connect(struct smc_sock *smc) ...@@ -769,21 +769,27 @@ static int __smc_connect(struct smc_sock *smc)
if (using_ipsec(smc)) if (using_ipsec(smc))
return smc_connect_decline_fallback(smc, SMC_CLC_DECL_IPSEC); 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 */ /* 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, return smc_connect_decline_fallback(smc,
SMC_CLC_DECL_GETVLANERR); SMC_CLC_DECL_GETVLANERR);
}
/* check if there is an ism device available */ /* check if there is an ism device available */
if (!smc_find_ism_device(smc, &ini) && if (!smc_find_ism_device(smc, ini) &&
!smc_connect_ism_vlan_setup(smc, &ini)) { !smc_connect_ism_vlan_setup(smc, ini)) {
/* ISM is supported for this connection */ /* ISM is supported for this connection */
ism_supported = true; ism_supported = true;
smc_type = SMC_TYPE_D; smc_type = SMC_TYPE_D;
} }
/* check if there is a rdma device available */ /* 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 is supported for this connection */
rdma_supported = true; rdma_supported = true;
if (ism_supported) if (ism_supported)
...@@ -793,29 +799,34 @@ static int __smc_connect(struct smc_sock *smc) ...@@ -793,29 +799,34 @@ static int __smc_connect(struct smc_sock *smc)
} }
/* if neither ISM nor RDMA are supported, fallback */ /* 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); return smc_connect_decline_fallback(smc, SMC_CLC_DECL_NOSMCDEV);
}
/* perform CLC handshake */ /* perform CLC handshake */
rc = smc_connect_clc(smc, smc_type, &aclc, &ini); rc = smc_connect_clc(smc, smc_type, &aclc, ini);
if (rc) { 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); return smc_connect_decline_fallback(smc, rc);
} }
/* depending on previous steps, connect using rdma or ism */ /* depending on previous steps, connect using rdma or ism */
if (rdma_supported && aclc.hdr.typev1 == SMC_TYPE_R) 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) 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 else
rc = SMC_CLC_DECL_MODEUNSUPP; rc = SMC_CLC_DECL_MODEUNSUPP;
if (rc) { 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); 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; return 0;
} }
...@@ -1219,14 +1230,14 @@ static void smc_find_ism_device_serv(struct smc_sock *new_smc, ...@@ -1219,14 +1230,14 @@ static void smc_find_ism_device_serv(struct smc_sock *new_smc,
if (!smcd_indicated(pclc->hdr.typev1)) if (!smcd_indicated(pclc->hdr.typev1))
goto not_found; goto not_found;
ini->is_smcd = true; /* prepare ISM check */ 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)) if (smc_find_ism_device(new_smc, ini))
goto not_found; goto not_found;
if (!smc_listen_ism_init(new_smc, ini)) if (!smc_listen_ism_init(new_smc, ini))
return; /* ISM device found */ return; /* ISM device found */
not_found: not_found:
ini->ism_dev = NULL; ini->ism_dev[0] = NULL;
ini->is_smcd = false; ini->is_smcd = false;
} }
...@@ -1319,7 +1330,7 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1319,7 +1330,7 @@ static void smc_listen_work(struct work_struct *work)
struct smc_clc_msg_accept_confirm cclc; struct smc_clc_msg_accept_confirm cclc;
struct smc_clc_msg_proposal_area *buf; struct smc_clc_msg_proposal_area *buf;
struct smc_clc_msg_proposal *pclc; struct smc_clc_msg_proposal *pclc;
struct smc_init_info ini = {0}; struct smc_init_info *ini = NULL;
int rc = 0; int rc = 0;
if (new_smc->listen_smc->sk.sk_state != SMC_LISTEN) if (new_smc->listen_smc->sk.sk_state != SMC_LISTEN)
...@@ -1363,8 +1374,14 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1363,8 +1374,14 @@ static void smc_listen_work(struct work_struct *work)
if (rc) if (rc)
goto out_decl; 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 */ /* 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; rc = SMC_CLC_DECL_GETVLANERR;
goto out_decl; goto out_decl;
} }
...@@ -1375,32 +1392,32 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1375,32 +1392,32 @@ static void smc_listen_work(struct work_struct *work)
smc_tx_init(new_smc); smc_tx_init(new_smc);
/* determine ISM or RoCE device used for connection */ /* 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) if (rc)
goto out_unlock; goto out_unlock;
/* send SMC Accept CLC message */ /* 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) if (rc)
goto out_unlock; goto out_unlock;
/* SMC-D does not need this lock any more */ /* SMC-D does not need this lock any more */
if (ini.is_smcd) if (ini->is_smcd)
mutex_unlock(&smc_server_lgr_pending); mutex_unlock(&smc_server_lgr_pending);
/* receive SMC Confirm CLC message */ /* receive SMC Confirm CLC message */
rc = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc), rc = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
SMC_CLC_CONFIRM, CLC_WAIT_TIME); SMC_CLC_CONFIRM, CLC_WAIT_TIME);
if (rc) { if (rc) {
if (!ini.is_smcd) if (!ini->is_smcd)
goto out_unlock; goto out_unlock;
goto out_decl; goto out_decl;
} }
/* finish worker */ /* finish worker */
if (!ini.is_smcd) { if (!ini->is_smcd) {
rc = smc_listen_rdma_finish(new_smc, &cclc, rc = smc_listen_rdma_finish(new_smc, &cclc,
ini.first_contact_local); ini->first_contact_local);
if (rc) if (rc)
goto out_unlock; goto out_unlock;
mutex_unlock(&smc_server_lgr_pending); mutex_unlock(&smc_server_lgr_pending);
...@@ -1412,8 +1429,9 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1412,8 +1429,9 @@ static void smc_listen_work(struct work_struct *work)
out_unlock: out_unlock:
mutex_unlock(&smc_server_lgr_pending); mutex_unlock(&smc_server_lgr_pending);
out_decl: 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: out_free:
kfree(ini);
kfree(buf); kfree(buf);
} }
......
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
#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
*/
extern struct proto smc_proto; extern struct proto smc_proto;
extern struct proto smc_proto6; extern struct proto smc_proto6;
......
...@@ -463,7 +463,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type, ...@@ -463,7 +463,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
/* add SMC-D specifics */ /* add SMC-D specifics */
plen += sizeof(*pclc_smcd); plen += sizeof(*pclc_smcd);
pclc_base->iparea_offset = htons(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); pclc_base->hdr.length = htons(plen);
......
...@@ -375,7 +375,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini) ...@@ -375,7 +375,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
int i; int i;
if (ini->is_smcd && ini->vlan_id) { 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; rc = SMC_CLC_DECL_ISMVLANERR;
goto out; goto out;
} }
...@@ -412,13 +412,13 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini) ...@@ -412,13 +412,13 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
lgr->conns_all = RB_ROOT; lgr->conns_all = RB_ROOT;
if (ini->is_smcd) { if (ini->is_smcd) {
/* SMC-D specific settings */ /* SMC-D specific settings */
get_device(&ini->ism_dev->dev); get_device(&ini->ism_dev[0]->dev);
lgr->peer_gid = ini->ism_peer_gid; lgr->peer_gid = ini->ism_peer_gid[0];
lgr->smcd = ini->ism_dev; lgr->smcd = ini->ism_dev[0];
lgr_list = &ini->ism_dev->lgr_list; lgr_list = &ini->ism_dev[0]->lgr_list;
lgr_lock = &lgr->smcd->lgr_lock; lgr_lock = &lgr->smcd->lgr_lock;
lgr->peer_shutdown = 0; lgr->peer_shutdown = 0;
atomic_inc(&ini->ism_dev->lgr_cnt); atomic_inc(&ini->ism_dev[0]->lgr_cnt);
} else { } else {
/* SMC-R specific settings */ /* SMC-R specific settings */
lgr->role = smc->listen_smc ? SMC_SERV : SMC_CLNT; lgr->role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
...@@ -449,7 +449,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini) ...@@ -449,7 +449,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
kfree(lgr); kfree(lgr);
ism_put_vlan: ism_put_vlan:
if (ini->is_smcd && ini->vlan_id) 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: out:
if (rc < 0) { if (rc < 0) {
if (rc == -ENOMEM) if (rc == -ENOMEM)
...@@ -1288,8 +1288,10 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini) ...@@ -1288,8 +1288,10 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
spinlock_t *lgr_lock; spinlock_t *lgr_lock;
int rc = 0; int rc = 0;
lgr_list = ini->is_smcd ? &ini->ism_dev->lgr_list : &smc_lgr_list.list; lgr_list = ini->is_smcd ? &ini->ism_dev[0]->lgr_list :
lgr_lock = ini->is_smcd ? &ini->ism_dev->lgr_lock : &smc_lgr_list.lock; &smc_lgr_list.list;
lgr_lock = ini->is_smcd ? &ini->ism_dev[0]->lgr_lock :
&smc_lgr_list.lock;
ini->first_contact_local = 1; ini->first_contact_local = 1;
role = smc->listen_smc ? SMC_SERV : SMC_CLNT; role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
if (role == SMC_CLNT && ini->first_contact_peer) 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) ...@@ -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) { list_for_each_entry(lgr, lgr_list, list) {
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_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)) && smcr_lgr_match(lgr, ini->ib_lcl, role, ini->ib_clcqpn)) &&
!lgr->sync_err && !lgr->sync_err &&
lgr->vlan_id == ini->vlan_id && lgr->vlan_id == ini->vlan_id &&
......
...@@ -301,8 +301,8 @@ struct smc_init_info { ...@@ -301,8 +301,8 @@ struct smc_init_info {
u8 ib_port; u8 ib_port;
u32 ib_clcqpn; u32 ib_clcqpn;
/* SMC-D */ /* SMC-D */
u64 ism_peer_gid; u64 ism_peer_gid[SMC_MAX_ISM_DEVS + 1];
struct smcd_dev *ism_dev; struct smcd_dev *ism_dev[SMC_MAX_ISM_DEVS + 1];
}; };
/* Find the connection associated with the given alert token in the link group. /* Find the connection associated with the given alert token in the link group.
......
...@@ -933,10 +933,10 @@ static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev, ...@@ -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) { 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 || (!ini->ism_peer_gid[0] ||
!smc_ism_cantalk(ini->ism_peer_gid, ini->vlan_id, !smc_ism_cantalk(ini->ism_peer_gid[0], ini->vlan_id,
ismdev))) { ismdev))) {
ini->ism_dev = ismdev; ini->ism_dev[0] = ismdev;
break; break;
} }
} }
...@@ -970,7 +970,7 @@ void smc_pnet_find_ism_resource(struct sock *sk, struct smc_init_info *ini) ...@@ -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); struct dst_entry *dst = sk_dst_get(sk);
ini->ism_dev = NULL; ini->ism_dev[0] = NULL;
if (!dst) if (!dst)
goto out; goto out;
if (!dst->dev) if (!dst->dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment