Commit b9a9ad78 authored by David S. Miller's avatar David S. Miller

Merge branch 'smc-next'

Ursula Braun says:

====================
net/smc: patches 2018-07-25

here are 4 more patches for SMC: The first one is just a small
code cleanup in preparation for patch 2. Patch 2 switches to the
use of the vlan-gid for VLAN traffic. Patch 3 improves diagnosis
when creating SMC connections. Patch 4 improves synchronization
between local and remote link groups.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f5375305 0d18a0cb
...@@ -43,6 +43,7 @@ enum { ...@@ -43,6 +43,7 @@ enum {
SMC_DIAG_LGRINFO, SMC_DIAG_LGRINFO,
SMC_DIAG_SHUTDOWN, SMC_DIAG_SHUTDOWN,
SMC_DIAG_DMBINFO, SMC_DIAG_DMBINFO,
SMC_DIAG_FALLBACK,
__SMC_DIAG_MAX, __SMC_DIAG_MAX,
}; };
...@@ -92,6 +93,11 @@ struct smc_diag_lgrinfo { ...@@ -92,6 +93,11 @@ struct smc_diag_lgrinfo {
__u8 role; __u8 role;
}; };
struct smc_diag_fallback {
__u32 reason;
__u32 peer_diagnosis;
};
struct smcd_diag_dmbinfo { /* SMC-D Socket internals */ struct smcd_diag_dmbinfo { /* SMC-D Socket internals */
__u32 linkid; /* Link identifier */ __u32 linkid; /* Link identifier */
__u64 peer_gid; /* Peer GID */ __u64 peer_gid; /* Peer GID */
......
This diff is collapsed.
...@@ -208,6 +208,8 @@ struct smc_sock { /* smc sock container */ ...@@ -208,6 +208,8 @@ struct smc_sock { /* smc sock container */
struct list_head accept_q; /* sockets to be accepted */ struct list_head accept_q; /* sockets to be accepted */
spinlock_t accept_q_lock; /* protects accept_q */ spinlock_t accept_q_lock; /* protects accept_q */
bool use_fallback; /* fallback to tcp */ bool use_fallback; /* fallback to tcp */
int fallback_rsn; /* reason for fallback */
u32 peer_diagnosis; /* decline reason from peer */
int sockopt_defer_accept; int sockopt_defer_accept;
/* sockopt TCP_DEFER_ACCEPT /* sockopt TCP_DEFER_ACCEPT
* value * value
......
...@@ -334,7 +334,11 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, ...@@ -334,7 +334,11 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
goto out; goto out;
} }
if (clcm->type == SMC_CLC_DECLINE) { if (clcm->type == SMC_CLC_DECLINE) {
reason_code = SMC_CLC_DECL_REPLY; struct smc_clc_msg_decline *dclc;
dclc = (struct smc_clc_msg_decline *)clcm;
reason_code = SMC_CLC_DECL_PEERDECL;
smc->peer_diagnosis = ntohl(dclc->peer_diagnosis);
if (((struct smc_clc_msg_decline *)buf)->hdr.flag) { if (((struct smc_clc_msg_decline *)buf)->hdr.flag) {
smc->conn.lgr->sync_err = 1; smc->conn.lgr->sync_err = 1;
smc_lgr_terminate(smc->conn.lgr); smc_lgr_terminate(smc->conn.lgr);
...@@ -378,7 +382,7 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info) ...@@ -378,7 +382,7 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
/* send CLC PROPOSAL message across internal TCP socket */ /* send CLC PROPOSAL message across internal TCP socket */
int smc_clc_send_proposal(struct smc_sock *smc, int smc_type, int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
struct smc_ib_device *ibdev, u8 ibport, struct smc_ib_device *ibdev, u8 ibport, u8 gid[],
struct smcd_dev *ismdev) struct smcd_dev *ismdev)
{ {
struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX]; struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX];
...@@ -409,7 +413,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type, ...@@ -409,7 +413,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
/* add SMC-R specifics */ /* add SMC-R specifics */
memcpy(pclc.lcl.id_for_peer, local_systemid, memcpy(pclc.lcl.id_for_peer, local_systemid,
sizeof(local_systemid)); sizeof(local_systemid));
memcpy(&pclc.lcl.gid, &ibdev->gid[ibport - 1], SMC_GID_SIZE); memcpy(&pclc.lcl.gid, gid, SMC_GID_SIZE);
memcpy(&pclc.lcl.mac, &ibdev->mac[ibport - 1], ETH_ALEN); memcpy(&pclc.lcl.mac, &ibdev->mac[ibport - 1], ETH_ALEN);
pclc.iparea_offset = htons(0); pclc.iparea_offset = htons(0);
} }
...@@ -492,8 +496,7 @@ int smc_clc_send_confirm(struct smc_sock *smc) ...@@ -492,8 +496,7 @@ int smc_clc_send_confirm(struct smc_sock *smc)
cclc.hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); cclc.hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
memcpy(cclc.lcl.id_for_peer, local_systemid, memcpy(cclc.lcl.id_for_peer, local_systemid,
sizeof(local_systemid)); sizeof(local_systemid));
memcpy(&cclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1], memcpy(&cclc.lcl.gid, link->gid, SMC_GID_SIZE);
SMC_GID_SIZE);
memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1],
ETH_ALEN); ETH_ALEN);
hton24(cclc.qpn, link->roce_qp->qp_num); hton24(cclc.qpn, link->roce_qp->qp_num);
...@@ -566,8 +569,7 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact) ...@@ -566,8 +569,7 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
link = &conn->lgr->lnk[SMC_SINGLE_LINK]; link = &conn->lgr->lnk[SMC_SINGLE_LINK];
memcpy(aclc.lcl.id_for_peer, local_systemid, memcpy(aclc.lcl.id_for_peer, local_systemid,
sizeof(local_systemid)); sizeof(local_systemid));
memcpy(&aclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1], memcpy(&aclc.lcl.gid, link->gid, SMC_GID_SIZE);
SMC_GID_SIZE);
memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1],
ETH_ALEN); ETH_ALEN);
hton24(aclc.qpn, link->roce_qp->qp_num); hton24(aclc.qpn, link->roce_qp->qp_num);
......
...@@ -28,15 +28,21 @@ ...@@ -28,15 +28,21 @@
#define SMC_TYPE_B 3 /* SMC-R and SMC-D */ #define SMC_TYPE_B 3 /* SMC-R and SMC-D */
#define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */ #define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */
#define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */ #define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */
#define SMC_CLC_DECL_TIMEOUT 0x02000000 /* timeout */ #define SMC_CLC_DECL_TIMEOUT_CL 0x02010000 /* timeout w4 QP confirm link */
#define SMC_CLC_DECL_TIMEOUT_AL 0x02020000 /* timeout w4 QP add link */
#define SMC_CLC_DECL_CNFERR 0x03000000 /* configuration error */ #define SMC_CLC_DECL_CNFERR 0x03000000 /* configuration error */
#define SMC_CLC_DECL_IPSEC 0x03030000 /* IPsec usage */ #define SMC_CLC_DECL_PEERNOSMC 0x03010000 /* peer did not indicate SMC */
#define SMC_CLC_DECL_IPSEC 0x03020000 /* IPsec usage */
#define SMC_CLC_DECL_NOSMCDEV 0x03030000 /* no SMC device found */
#define SMC_CLC_DECL_MODEUNSUPP 0x03040000 /* smc modes do not match (R or D)*/
#define SMC_CLC_DECL_RMBE_EC 0x03050000 /* peer has eyecatcher in RMBE */
#define SMC_CLC_DECL_OPTUNSUPP 0x03060000 /* fastopen sockopt not supported */
#define SMC_CLC_DECL_SYNCERR 0x04000000 /* synchronization error */ #define SMC_CLC_DECL_SYNCERR 0x04000000 /* synchronization error */
#define SMC_CLC_DECL_REPLY 0x06000000 /* reply to a received decline */ #define SMC_CLC_DECL_PEERDECL 0x05000000 /* peer declined during handshake */
#define SMC_CLC_DECL_INTERR 0x99990000 /* internal error */ #define SMC_CLC_DECL_INTERR 0x99990000 /* internal error */
#define SMC_CLC_DECL_TCL 0x02040000 /* timeout w4 QP confirm */ #define SMC_CLC_DECL_ERR_RTOK 0x99990001 /* rtoken handling failed */
#define SMC_CLC_DECL_SEND 0x07000000 /* sending problem */ #define SMC_CLC_DECL_ERR_RDYLNK 0x99990002 /* ib ready link failed */
#define SMC_CLC_DECL_RMBE_EC 0x08000000 /* peer has eyecatcher in RMBE */ #define SMC_CLC_DECL_ERR_REGRMB 0x99990003 /* reg rmb failed */
struct smc_clc_msg_hdr { /* header1 of clc messages */ struct smc_clc_msg_hdr { /* header1 of clc messages */
u8 eyecatcher[4]; /* eye catcher */ u8 eyecatcher[4]; /* eye catcher */
...@@ -179,7 +185,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, ...@@ -179,7 +185,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
u8 expected_type); u8 expected_type);
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info); int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
int smc_clc_send_proposal(struct smc_sock *smc, int smc_type, int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
struct smc_ib_device *smcibdev, u8 ibport, struct smc_ib_device *smcibdev, u8 ibport, u8 gid[],
struct smcd_dev *ismdev); struct smcd_dev *ismdev);
int smc_clc_send_confirm(struct smc_sock *smc); int smc_clc_send_confirm(struct smc_sock *smc);
int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact); int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define SMC_LGR_NUM_INCR 256 #define SMC_LGR_NUM_INCR 256
#define SMC_LGR_FREE_DELAY_SERV (600 * HZ) #define SMC_LGR_FREE_DELAY_SERV (600 * HZ)
#define SMC_LGR_FREE_DELAY_CLNT (SMC_LGR_FREE_DELAY_SERV + 10 * HZ) #define SMC_LGR_FREE_DELAY_CLNT (SMC_LGR_FREE_DELAY_SERV + 10 * HZ)
#define SMC_LGR_FREE_DELAY_FAST (8 * HZ)
static struct smc_lgr_list smc_lgr_list = { /* established link groups */ static struct smc_lgr_list smc_lgr_list = { /* established link groups */
.lock = __SPIN_LOCK_UNLOCKED(smc_lgr_list.lock), .lock = __SPIN_LOCK_UNLOCKED(smc_lgr_list.lock),
...@@ -51,6 +52,11 @@ static void smc_lgr_schedule_free_work(struct smc_link_group *lgr) ...@@ -51,6 +52,11 @@ static void smc_lgr_schedule_free_work(struct smc_link_group *lgr)
SMC_LGR_FREE_DELAY_CLNT : SMC_LGR_FREE_DELAY_SERV); SMC_LGR_FREE_DELAY_CLNT : SMC_LGR_FREE_DELAY_SERV);
} }
void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr)
{
mod_delayed_work(system_wq, &lgr->free_work, SMC_LGR_FREE_DELAY_FAST);
}
/* Register connection's alert token in our lookup structure. /* Register connection's alert token in our lookup structure.
* To use rbtrees we have to implement our own insert core. * To use rbtrees we have to implement our own insert core.
* Requires @conns_lock * Requires @conns_lock
...@@ -133,6 +139,20 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn) ...@@ -133,6 +139,20 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
smc_lgr_schedule_free_work(lgr); smc_lgr_schedule_free_work(lgr);
} }
/* Send delete link, either as client to request the initiation
* of the DELETE LINK sequence from server; or as server to
* initiate the delete processing. See smc_llc_rx_delete_link().
*/
static int smc_link_send_delete(struct smc_link *lnk)
{
if (lnk->state == SMC_LNK_ACTIVE &&
!smc_llc_send_delete_link(lnk, SMC_LLC_REQ, true)) {
smc_llc_link_deleting(lnk);
return 0;
}
return -ENOTCONN;
}
static void smc_lgr_free_work(struct work_struct *work) static void smc_lgr_free_work(struct work_struct *work)
{ {
struct smc_link_group *lgr = container_of(to_delayed_work(work), struct smc_link_group *lgr = container_of(to_delayed_work(work),
...@@ -153,10 +173,21 @@ static void smc_lgr_free_work(struct work_struct *work) ...@@ -153,10 +173,21 @@ static void smc_lgr_free_work(struct work_struct *work)
list_del_init(&lgr->list); /* remove from smc_lgr_list */ list_del_init(&lgr->list); /* remove from smc_lgr_list */
free: free:
spin_unlock_bh(&smc_lgr_list.lock); spin_unlock_bh(&smc_lgr_list.lock);
if (!lgr->is_smcd && !lgr->terminating) {
/* try to send del link msg, on error free lgr immediately */
if (!smc_link_send_delete(&lgr->lnk[SMC_SINGLE_LINK])) {
/* reschedule in case we never receive a response */
smc_lgr_schedule_free_work(lgr);
return;
}
}
if (!delayed_work_pending(&lgr->free_work)) { if (!delayed_work_pending(&lgr->free_work)) {
if (!lgr->is_smcd && struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
lgr->lnk[SMC_SINGLE_LINK].state != SMC_LNK_INACTIVE)
smc_llc_link_inactive(&lgr->lnk[SMC_SINGLE_LINK]); if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE)
smc_llc_link_inactive(lnk);
smc_lgr_free(lgr); smc_lgr_free(lgr);
} }
} }
...@@ -219,6 +250,10 @@ static int smc_lgr_create(struct smc_sock *smc, bool is_smcd, ...@@ -219,6 +250,10 @@ static int smc_lgr_create(struct smc_sock *smc, bool is_smcd,
get_random_bytes(rndvec, sizeof(rndvec)); get_random_bytes(rndvec, sizeof(rndvec));
lnk->psn_initial = rndvec[0] + (rndvec[1] << 8) + lnk->psn_initial = rndvec[0] + (rndvec[1] << 8) +
(rndvec[2] << 16); (rndvec[2] << 16);
rc = smc_ib_determine_gid(lnk->smcibdev, lnk->ibport,
vlan_id, lnk->gid, &lnk->sgid_index);
if (rc)
goto free_lgr;
rc = smc_llc_link_init(lnk); rc = smc_llc_link_init(lnk);
if (rc) if (rc)
goto free_lgr; goto free_lgr;
...@@ -522,37 +557,6 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id) ...@@ -522,37 +557,6 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id)
return rc; return rc;
} }
/* determine the link gid matching the vlan id of the link group */
static int smc_link_determine_gid(struct smc_link_group *lgr)
{
struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
struct ib_gid_attr gattr;
union ib_gid gid;
int i;
if (!lgr->vlan_id) {
lnk->gid = lnk->smcibdev->gid[lnk->ibport - 1];
return 0;
}
for (i = 0; i < lnk->smcibdev->pattr[lnk->ibport - 1].gid_tbl_len;
i++) {
if (ib_query_gid(lnk->smcibdev->ibdev, lnk->ibport, i, &gid,
&gattr))
continue;
if (gattr.ndev) {
if (is_vlan_dev(gattr.ndev) &&
vlan_dev_vlan_id(gattr.ndev) == lgr->vlan_id) {
lnk->gid = gid;
dev_put(gattr.ndev);
return 0;
}
dev_put(gattr.ndev);
}
}
return -ENODEV;
}
static bool smcr_lgr_match(struct smc_link_group *lgr, static bool smcr_lgr_match(struct smc_link_group *lgr,
struct smc_clc_msg_local *lcl, struct smc_clc_msg_local *lcl,
enum smc_lgr_role role) enum smc_lgr_role role)
...@@ -631,8 +635,6 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact, ...@@ -631,8 +635,6 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
if (rc) if (rc)
goto out; goto out;
smc_lgr_register_conn(conn); /* add smc conn to lgr */ smc_lgr_register_conn(conn); /* add smc conn to lgr */
if (!is_smcd)
rc = smc_link_determine_gid(conn->lgr);
} }
conn->local_tx_ctrl.common.type = SMC_CDC_MSG_TYPE; conn->local_tx_ctrl.common.type = SMC_CDC_MSG_TYPE;
conn->local_tx_ctrl.len = SMC_WR_TX_SIZE; conn->local_tx_ctrl.len = SMC_WR_TX_SIZE;
...@@ -1013,8 +1015,14 @@ void smc_core_exit(void) ...@@ -1013,8 +1015,14 @@ void smc_core_exit(void)
spin_unlock_bh(&smc_lgr_list.lock); spin_unlock_bh(&smc_lgr_list.lock);
list_for_each_entry_safe(lgr, lg, &lgr_freeing_list, list) { list_for_each_entry_safe(lgr, lg, &lgr_freeing_list, list) {
list_del_init(&lgr->list); list_del_init(&lgr->list);
if (!lgr->is_smcd) if (!lgr->is_smcd) {
smc_llc_link_inactive(&lgr->lnk[SMC_SINGLE_LINK]); struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
if (lnk->state == SMC_LNK_ACTIVE)
smc_llc_send_delete_link(lnk, SMC_LLC_REQ,
false);
smc_llc_link_inactive(lnk);
}
cancel_delayed_work_sync(&lgr->free_work); cancel_delayed_work_sync(&lgr->free_work);
smc_lgr_free(lgr); /* free link group */ smc_lgr_free(lgr); /* free link group */
} }
......
...@@ -34,7 +34,8 @@ enum smc_lgr_role { /* possible roles of a link group */ ...@@ -34,7 +34,8 @@ enum smc_lgr_role { /* possible roles of a link group */
enum smc_link_state { /* possible states of a link */ enum smc_link_state { /* possible states of a link */
SMC_LNK_INACTIVE, /* link is inactive */ SMC_LNK_INACTIVE, /* link is inactive */
SMC_LNK_ACTIVATING, /* link is being activated */ SMC_LNK_ACTIVATING, /* link is being activated */
SMC_LNK_ACTIVE /* link is active */ SMC_LNK_ACTIVE, /* link is active */
SMC_LNK_DELETING, /* link is being deleted */
}; };
#define SMC_WR_BUF_SIZE 48 /* size of work request buffer */ #define SMC_WR_BUF_SIZE 48 /* size of work request buffer */
...@@ -84,14 +85,15 @@ struct smc_link { ...@@ -84,14 +85,15 @@ struct smc_link {
wait_queue_head_t wr_reg_wait; /* wait for wr_reg result */ wait_queue_head_t wr_reg_wait; /* wait for wr_reg result */
enum smc_wr_reg_state wr_reg_state; /* state of wr_reg request */ enum smc_wr_reg_state wr_reg_state; /* state of wr_reg request */
union ib_gid gid; /* gid matching used vlan id */ u8 gid[SMC_GID_SIZE];/* gid matching used vlan id*/
u8 sgid_index; /* gid index for vlan id */
u32 peer_qpn; /* QP number of peer */ u32 peer_qpn; /* QP number of peer */
enum ib_mtu path_mtu; /* used mtu */ enum ib_mtu path_mtu; /* used mtu */
enum ib_mtu peer_mtu; /* mtu size of peer */ enum ib_mtu peer_mtu; /* mtu size of peer */
u32 psn_initial; /* QP tx initial packet seqno */ u32 psn_initial; /* QP tx initial packet seqno */
u32 peer_psn; /* QP rx initial packet seqno */ u32 peer_psn; /* QP rx initial packet seqno */
u8 peer_mac[ETH_ALEN]; /* = gid[8:10||13:15] */ u8 peer_mac[ETH_ALEN]; /* = gid[8:10||13:15] */
u8 peer_gid[sizeof(union ib_gid)]; /* gid of peer*/ u8 peer_gid[SMC_GID_SIZE]; /* gid of peer*/
u8 link_id; /* unique # within link group */ u8 link_id; /* unique # within link group */
enum smc_link_state state; /* state of link */ enum smc_link_state state; /* state of link */
...@@ -264,6 +266,7 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact, ...@@ -264,6 +266,7 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
struct smc_clc_msg_local *lcl, struct smcd_dev *smcd, struct smc_clc_msg_local *lcl, struct smcd_dev *smcd,
u64 peer_gid); u64 peer_gid);
void smcd_conn_free(struct smc_connection *conn); void smcd_conn_free(struct smc_connection *conn);
void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr);
void smc_core_exit(void); void smc_core_exit(void);
static inline struct smc_link_group *smc_get_lgr(struct smc_link *link) static inline struct smc_link_group *smc_get_lgr(struct smc_link *link)
......
...@@ -79,6 +79,7 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb, ...@@ -79,6 +79,7 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
struct nlattr *bc) struct nlattr *bc)
{ {
struct smc_sock *smc = smc_sk(sk); struct smc_sock *smc = smc_sk(sk);
struct smc_diag_fallback fallback;
struct user_namespace *user_ns; struct user_namespace *user_ns;
struct smc_diag_msg *r; struct smc_diag_msg *r;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
...@@ -101,6 +102,11 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb, ...@@ -101,6 +102,11 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
if (smc_diag_msg_attrs_fill(sk, skb, r, user_ns)) if (smc_diag_msg_attrs_fill(sk, skb, r, user_ns))
goto errout; goto errout;
fallback.reason = smc->fallback_rsn;
fallback.peer_diagnosis = smc->peer_diagnosis;
if (nla_put(skb, SMC_DIAG_FALLBACK, sizeof(fallback), &fallback) < 0)
goto errout;
if ((req->diag_ext & (1 << (SMC_DIAG_CONNINFO - 1))) && if ((req->diag_ext & (1 << (SMC_DIAG_CONNINFO - 1))) &&
smc->conn.alert_token_local) { smc->conn.alert_token_local) {
struct smc_connection *conn = &smc->conn; struct smc_connection *conn = &smc->conn;
...@@ -154,7 +160,7 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb, ...@@ -154,7 +160,7 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
smc->conn.lgr->lnk[0].smcibdev->ibdev->name, smc->conn.lgr->lnk[0].smcibdev->ibdev->name,
sizeof(smc->conn.lgr->lnk[0].smcibdev->ibdev->name)); sizeof(smc->conn.lgr->lnk[0].smcibdev->ibdev->name));
smc_gid_be16_convert(linfo.lnk[0].gid, smc_gid_be16_convert(linfo.lnk[0].gid,
smc->conn.lgr->lnk[0].gid.raw); smc->conn.lgr->lnk[0].gid);
smc_gid_be16_convert(linfo.lnk[0].peer_gid, smc_gid_be16_convert(linfo.lnk[0].peer_gid,
smc->conn.lgr->lnk[0].peer_gid); smc->conn.lgr->lnk[0].peer_gid);
......
...@@ -68,7 +68,7 @@ static int smc_ib_modify_qp_rtr(struct smc_link *lnk) ...@@ -68,7 +68,7 @@ static int smc_ib_modify_qp_rtr(struct smc_link *lnk)
qp_attr.path_mtu = min(lnk->path_mtu, lnk->peer_mtu); qp_attr.path_mtu = min(lnk->path_mtu, lnk->peer_mtu);
qp_attr.ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE; qp_attr.ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE;
rdma_ah_set_port_num(&qp_attr.ah_attr, lnk->ibport); rdma_ah_set_port_num(&qp_attr.ah_attr, lnk->ibport);
rdma_ah_set_grh(&qp_attr.ah_attr, NULL, 0, 0, 1, 0); rdma_ah_set_grh(&qp_attr.ah_attr, NULL, 0, lnk->sgid_index, 1, 0);
rdma_ah_set_dgid_raw(&qp_attr.ah_attr, lnk->peer_gid); rdma_ah_set_dgid_raw(&qp_attr.ah_attr, lnk->peer_gid);
memcpy(&qp_attr.ah_attr.roce.dmac, lnk->peer_mac, memcpy(&qp_attr.ah_attr.roce.dmac, lnk->peer_mac,
sizeof(lnk->peer_mac)); sizeof(lnk->peer_mac));
...@@ -142,13 +142,13 @@ int smc_ib_ready_link(struct smc_link *lnk) ...@@ -142,13 +142,13 @@ int smc_ib_ready_link(struct smc_link *lnk)
return rc; return rc;
} }
static int smc_ib_fill_gid_and_mac(struct smc_ib_device *smcibdev, u8 ibport) static int smc_ib_fill_mac(struct smc_ib_device *smcibdev, u8 ibport)
{ {
struct ib_gid_attr gattr; struct ib_gid_attr gattr;
union ib_gid gid;
int rc; int rc;
rc = ib_query_gid(smcibdev->ibdev, ibport, 0, rc = ib_query_gid(smcibdev->ibdev, ibport, 0, &gid, &gattr);
&smcibdev->gid[ibport - 1], &gattr);
if (rc || !gattr.ndev) if (rc || !gattr.ndev)
return -ENODEV; return -ENODEV;
...@@ -175,6 +175,37 @@ bool smc_ib_port_active(struct smc_ib_device *smcibdev, u8 ibport) ...@@ -175,6 +175,37 @@ bool smc_ib_port_active(struct smc_ib_device *smcibdev, u8 ibport)
return smcibdev->pattr[ibport - 1].state == IB_PORT_ACTIVE; return smcibdev->pattr[ibport - 1].state == IB_PORT_ACTIVE;
} }
/* determine the gid for an ib-device port and vlan id */
int smc_ib_determine_gid(struct smc_ib_device *smcibdev, u8 ibport,
unsigned short vlan_id, u8 gid[], u8 *sgid_index)
{
struct ib_gid_attr gattr;
union ib_gid _gid;
int i;
for (i = 0; i < smcibdev->pattr[ibport - 1].gid_tbl_len; i++) {
memset(&_gid, 0, SMC_GID_SIZE);
memset(&gattr, 0, sizeof(gattr));
if (ib_query_gid(smcibdev->ibdev, ibport, i, &_gid, &gattr))
continue;
if (!gattr.ndev)
continue;
if (((!vlan_id && !is_vlan_dev(gattr.ndev)) ||
(vlan_id && is_vlan_dev(gattr.ndev) &&
vlan_dev_vlan_id(gattr.ndev) == vlan_id)) &&
gattr.gid_type == IB_GID_TYPE_IB) {
if (gid)
memcpy(gid, &_gid, SMC_GID_SIZE);
if (sgid_index)
*sgid_index = i;
dev_put(gattr.ndev);
return 0;
}
dev_put(gattr.ndev);
}
return -ENODEV;
}
static int smc_ib_remember_port_attr(struct smc_ib_device *smcibdev, u8 ibport) static int smc_ib_remember_port_attr(struct smc_ib_device *smcibdev, u8 ibport)
{ {
int rc; int rc;
...@@ -186,7 +217,7 @@ static int smc_ib_remember_port_attr(struct smc_ib_device *smcibdev, u8 ibport) ...@@ -186,7 +217,7 @@ static int smc_ib_remember_port_attr(struct smc_ib_device *smcibdev, u8 ibport)
if (rc) if (rc)
goto out; goto out;
/* the SMC protocol requires specification of the RoCE MAC address */ /* the SMC protocol requires specification of the RoCE MAC address */
rc = smc_ib_fill_gid_and_mac(smcibdev, ibport); rc = smc_ib_fill_mac(smcibdev, ibport);
if (rc) if (rc)
goto out; goto out;
if (!strncmp(local_systemid, SMC_LOCAL_SYSTEMID_RESET, if (!strncmp(local_systemid, SMC_LOCAL_SYSTEMID_RESET,
......
...@@ -40,7 +40,6 @@ struct smc_ib_device { /* ib-device infos for smc */ ...@@ -40,7 +40,6 @@ struct smc_ib_device { /* ib-device infos for smc */
struct tasklet_struct recv_tasklet; /* called by recv cq handler */ struct tasklet_struct recv_tasklet; /* called by recv cq handler */
char mac[SMC_MAX_PORTS][ETH_ALEN]; char mac[SMC_MAX_PORTS][ETH_ALEN];
/* mac address per port*/ /* mac address per port*/
union ib_gid gid[SMC_MAX_PORTS]; /* gid per port */
u8 pnetid[SMC_MAX_PORTS][SMC_MAX_PNETID_LEN]; u8 pnetid[SMC_MAX_PORTS][SMC_MAX_PNETID_LEN];
/* pnetid per port */ /* pnetid per port */
u8 initialized : 1; /* ib dev CQ, evthdl done */ u8 initialized : 1; /* ib dev CQ, evthdl done */
...@@ -77,4 +76,6 @@ void smc_ib_sync_sg_for_cpu(struct smc_ib_device *smcibdev, ...@@ -77,4 +76,6 @@ void smc_ib_sync_sg_for_cpu(struct smc_ib_device *smcibdev,
void smc_ib_sync_sg_for_device(struct smc_ib_device *smcibdev, void smc_ib_sync_sg_for_device(struct smc_ib_device *smcibdev,
struct smc_buf_desc *buf_slot, struct smc_buf_desc *buf_slot,
enum dma_data_direction data_direction); enum dma_data_direction data_direction);
int smc_ib_determine_gid(struct smc_ib_device *smcibdev, u8 ibport,
unsigned short vlan_id, u8 gid[], u8 *sgid_index);
#endif #endif
...@@ -182,8 +182,7 @@ static int smc_llc_add_pending_send(struct smc_link *link, ...@@ -182,8 +182,7 @@ static int smc_llc_add_pending_send(struct smc_link *link,
} }
/* high-level API to send LLC confirm link */ /* high-level API to send LLC confirm link */
int smc_llc_send_confirm_link(struct smc_link *link, u8 mac[], int smc_llc_send_confirm_link(struct smc_link *link,
union ib_gid *gid,
enum smc_llc_reqresp reqresp) enum smc_llc_reqresp reqresp)
{ {
struct smc_link_group *lgr = smc_get_lgr(link); struct smc_link_group *lgr = smc_get_lgr(link);
...@@ -202,8 +201,9 @@ int smc_llc_send_confirm_link(struct smc_link *link, u8 mac[], ...@@ -202,8 +201,9 @@ int smc_llc_send_confirm_link(struct smc_link *link, u8 mac[],
confllc->hd.flags |= SMC_LLC_FLAG_NO_RMBE_EYEC; confllc->hd.flags |= SMC_LLC_FLAG_NO_RMBE_EYEC;
if (reqresp == SMC_LLC_RESP) if (reqresp == SMC_LLC_RESP)
confllc->hd.flags |= SMC_LLC_FLAG_RESP; confllc->hd.flags |= SMC_LLC_FLAG_RESP;
memcpy(confllc->sender_mac, mac, ETH_ALEN); memcpy(confllc->sender_mac, link->smcibdev->mac[link->ibport - 1],
memcpy(confllc->sender_gid, gid, SMC_GID_SIZE); ETH_ALEN);
memcpy(confllc->sender_gid, link->gid, SMC_GID_SIZE);
hton24(confllc->sender_qp_num, link->roce_qp->qp_num); hton24(confllc->sender_qp_num, link->roce_qp->qp_num);
confllc->link_num = link->link_id; confllc->link_num = link->link_id;
memcpy(confllc->link_uid, lgr->id, SMC_LGR_ID_SIZE); memcpy(confllc->link_uid, lgr->id, SMC_LGR_ID_SIZE);
...@@ -240,8 +240,7 @@ static int smc_llc_send_confirm_rkey(struct smc_link *link, ...@@ -240,8 +240,7 @@ static int smc_llc_send_confirm_rkey(struct smc_link *link,
/* prepare an add link message */ /* prepare an add link message */
static void smc_llc_prep_add_link(struct smc_llc_msg_add_link *addllc, static void smc_llc_prep_add_link(struct smc_llc_msg_add_link *addllc,
struct smc_link *link, u8 mac[], struct smc_link *link, u8 mac[], u8 gid[],
union ib_gid *gid,
enum smc_llc_reqresp reqresp) enum smc_llc_reqresp reqresp)
{ {
memset(addllc, 0, sizeof(*addllc)); memset(addllc, 0, sizeof(*addllc));
...@@ -258,8 +257,7 @@ static void smc_llc_prep_add_link(struct smc_llc_msg_add_link *addllc, ...@@ -258,8 +257,7 @@ static void smc_llc_prep_add_link(struct smc_llc_msg_add_link *addllc,
} }
/* send ADD LINK request or response */ /* send ADD LINK request or response */
int smc_llc_send_add_link(struct smc_link *link, u8 mac[], int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
union ib_gid *gid,
enum smc_llc_reqresp reqresp) enum smc_llc_reqresp reqresp)
{ {
struct smc_llc_msg_add_link *addllc; struct smc_llc_msg_add_link *addllc;
...@@ -280,7 +278,7 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[], ...@@ -280,7 +278,7 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[],
/* prepare a delete link message */ /* prepare a delete link message */
static void smc_llc_prep_delete_link(struct smc_llc_msg_del_link *delllc, static void smc_llc_prep_delete_link(struct smc_llc_msg_del_link *delllc,
struct smc_link *link, struct smc_link *link,
enum smc_llc_reqresp reqresp) enum smc_llc_reqresp reqresp, bool orderly)
{ {
memset(delllc, 0, sizeof(*delllc)); memset(delllc, 0, sizeof(*delllc));
delllc->hd.common.type = SMC_LLC_DELETE_LINK; delllc->hd.common.type = SMC_LLC_DELETE_LINK;
...@@ -289,13 +287,14 @@ static void smc_llc_prep_delete_link(struct smc_llc_msg_del_link *delllc, ...@@ -289,13 +287,14 @@ static void smc_llc_prep_delete_link(struct smc_llc_msg_del_link *delllc,
delllc->hd.flags |= SMC_LLC_FLAG_RESP; delllc->hd.flags |= SMC_LLC_FLAG_RESP;
/* DEL_LINK_ALL because only 1 link supported */ /* DEL_LINK_ALL because only 1 link supported */
delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL; delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL;
delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY; if (orderly)
delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
delllc->link_num = link->link_id; delllc->link_num = link->link_id;
} }
/* send DELETE LINK request or response */ /* send DELETE LINK request or response */
int smc_llc_send_delete_link(struct smc_link *link, int smc_llc_send_delete_link(struct smc_link *link,
enum smc_llc_reqresp reqresp) enum smc_llc_reqresp reqresp, bool orderly)
{ {
struct smc_llc_msg_del_link *delllc; struct smc_llc_msg_del_link *delllc;
struct smc_wr_tx_pend_priv *pend; struct smc_wr_tx_pend_priv *pend;
...@@ -306,7 +305,7 @@ int smc_llc_send_delete_link(struct smc_link *link, ...@@ -306,7 +305,7 @@ int smc_llc_send_delete_link(struct smc_link *link,
if (rc) if (rc)
return rc; return rc;
delllc = (struct smc_llc_msg_del_link *)wr_buf; delllc = (struct smc_llc_msg_del_link *)wr_buf;
smc_llc_prep_delete_link(delllc, link, reqresp); smc_llc_prep_delete_link(delllc, link, reqresp, orderly);
/* send llc message */ /* send llc message */
rc = smc_wr_tx_send(link, pend); rc = smc_wr_tx_send(link, pend);
return rc; return rc;
...@@ -422,14 +421,12 @@ static void smc_llc_rx_add_link(struct smc_link *link, ...@@ -422,14 +421,12 @@ static void smc_llc_rx_add_link(struct smc_link *link,
if (lgr->role == SMC_SERV) { if (lgr->role == SMC_SERV) {
smc_llc_prep_add_link(llc, link, smc_llc_prep_add_link(llc, link,
link->smcibdev->mac[link->ibport - 1], link->smcibdev->mac[link->ibport - 1],
&link->smcibdev->gid[link->ibport - 1], link->gid, SMC_LLC_REQ);
SMC_LLC_REQ);
} else { } else {
smc_llc_prep_add_link(llc, link, smc_llc_prep_add_link(llc, link,
link->smcibdev->mac[link->ibport - 1], link->smcibdev->mac[link->ibport - 1],
&link->smcibdev->gid[link->ibport - 1], link->gid, SMC_LLC_RESP);
SMC_LLC_RESP);
} }
smc_llc_send_message(link, llc, sizeof(*llc)); smc_llc_send_message(link, llc, sizeof(*llc));
} }
...@@ -442,17 +439,19 @@ static void smc_llc_rx_delete_link(struct smc_link *link, ...@@ -442,17 +439,19 @@ static void smc_llc_rx_delete_link(struct smc_link *link,
if (llc->hd.flags & SMC_LLC_FLAG_RESP) { if (llc->hd.flags & SMC_LLC_FLAG_RESP) {
if (lgr->role == SMC_SERV) if (lgr->role == SMC_SERV)
smc_lgr_terminate(lgr); smc_lgr_schedule_free_work_fast(lgr);
} else { } else {
smc_lgr_forget(lgr);
smc_llc_link_deleting(link);
if (lgr->role == SMC_SERV) { if (lgr->role == SMC_SERV) {
smc_lgr_forget(lgr); /* client asks to delete this link, send request */
smc_llc_prep_delete_link(llc, link, SMC_LLC_REQ); smc_llc_prep_delete_link(llc, link, SMC_LLC_REQ, true);
smc_llc_send_message(link, llc, sizeof(*llc));
} else { } else {
smc_llc_prep_delete_link(llc, link, SMC_LLC_RESP); /* server requests to delete this link, send response */
smc_llc_send_message(link, llc, sizeof(*llc)); smc_llc_prep_delete_link(llc, link, SMC_LLC_RESP, true);
smc_lgr_terminate(lgr);
} }
smc_llc_send_message(link, llc, sizeof(*llc));
smc_lgr_schedule_free_work_fast(lgr);
} }
} }
...@@ -626,6 +625,11 @@ void smc_llc_link_active(struct smc_link *link, int testlink_time) ...@@ -626,6 +625,11 @@ void smc_llc_link_active(struct smc_link *link, int testlink_time)
} }
} }
void smc_llc_link_deleting(struct smc_link *link)
{
link->state = SMC_LNK_DELETING;
}
/* called in tasklet context */ /* called in tasklet context */
void smc_llc_link_inactive(struct smc_link *link) void smc_llc_link_inactive(struct smc_link *link)
{ {
......
...@@ -36,14 +36,15 @@ enum smc_llc_msg_type { ...@@ -36,14 +36,15 @@ enum smc_llc_msg_type {
}; };
/* transmit */ /* transmit */
int smc_llc_send_confirm_link(struct smc_link *lnk, u8 mac[], union ib_gid *gid, int smc_llc_send_confirm_link(struct smc_link *lnk,
enum smc_llc_reqresp reqresp); enum smc_llc_reqresp reqresp);
int smc_llc_send_add_link(struct smc_link *link, u8 mac[], union ib_gid *gid, int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
enum smc_llc_reqresp reqresp); enum smc_llc_reqresp reqresp);
int smc_llc_send_delete_link(struct smc_link *link, int smc_llc_send_delete_link(struct smc_link *link,
enum smc_llc_reqresp reqresp); enum smc_llc_reqresp reqresp, bool orderly);
int smc_llc_link_init(struct smc_link *link); int smc_llc_link_init(struct smc_link *link);
void smc_llc_link_active(struct smc_link *link, int testlink_time); void smc_llc_link_active(struct smc_link *link, int testlink_time);
void smc_llc_link_deleting(struct smc_link *link);
void smc_llc_link_inactive(struct smc_link *link); void smc_llc_link_inactive(struct smc_link *link);
void smc_llc_link_clear(struct smc_link *link); void smc_llc_link_clear(struct smc_link *link);
int smc_llc_do_confirm_rkey(struct smc_link *link, int smc_llc_do_confirm_rkey(struct smc_link *link,
......
...@@ -535,11 +535,13 @@ static struct net_device *pnet_find_base_ndev(struct net_device *ndev) ...@@ -535,11 +535,13 @@ static struct net_device *pnet_find_base_ndev(struct net_device *ndev)
} }
/* Determine the corresponding IB device port based on the hardware PNETID. /* Determine the corresponding IB device port based on the hardware PNETID.
* Searching stops at the first matching active IB device port. * Searching stops at the first matching active IB device port with vlan_id
* configured.
*/ */
static void smc_pnet_find_roce_by_pnetid(struct net_device *ndev, static void smc_pnet_find_roce_by_pnetid(struct net_device *ndev,
struct smc_ib_device **smcibdev, struct smc_ib_device **smcibdev,
u8 *ibport) u8 *ibport, unsigned short vlan_id,
u8 gid[])
{ {
u8 ndev_pnetid[SMC_MAX_PNETID_LEN]; u8 ndev_pnetid[SMC_MAX_PNETID_LEN];
struct smc_ib_device *ibdev; struct smc_ib_device *ibdev;
...@@ -553,15 +555,20 @@ static void smc_pnet_find_roce_by_pnetid(struct net_device *ndev, ...@@ -553,15 +555,20 @@ static void smc_pnet_find_roce_by_pnetid(struct net_device *ndev,
spin_lock(&smc_ib_devices.lock); spin_lock(&smc_ib_devices.lock);
list_for_each_entry(ibdev, &smc_ib_devices.list, list) { list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
for (i = 1; i <= SMC_MAX_PORTS; i++) { for (i = 1; i <= SMC_MAX_PORTS; i++) {
if (!rdma_is_port_valid(ibdev->ibdev, i))
continue;
if (!memcmp(ibdev->pnetid[i - 1], ndev_pnetid, if (!memcmp(ibdev->pnetid[i - 1], ndev_pnetid,
SMC_MAX_PNETID_LEN) && SMC_MAX_PNETID_LEN) &&
smc_ib_port_active(ibdev, i)) { smc_ib_port_active(ibdev, i) &&
!smc_ib_determine_gid(ibdev, i, vlan_id, gid,
NULL)) {
*smcibdev = ibdev; *smcibdev = ibdev;
*ibport = i; *ibport = i;
break; goto out;
} }
} }
} }
out:
spin_unlock(&smc_ib_devices.lock); spin_unlock(&smc_ib_devices.lock);
} }
...@@ -589,7 +596,8 @@ static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev, ...@@ -589,7 +596,8 @@ static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev,
/* Lookup of coupled ib_device via SMC pnet table */ /* Lookup of coupled ib_device via SMC pnet table */
static void smc_pnet_find_roce_by_table(struct net_device *netdev, static void smc_pnet_find_roce_by_table(struct net_device *netdev,
struct smc_ib_device **smcibdev, struct smc_ib_device **smcibdev,
u8 *ibport) u8 *ibport, unsigned short vlan_id,
u8 gid[])
{ {
struct smc_pnetentry *pnetelem; struct smc_pnetentry *pnetelem;
...@@ -597,7 +605,10 @@ static void smc_pnet_find_roce_by_table(struct net_device *netdev, ...@@ -597,7 +605,10 @@ static void smc_pnet_find_roce_by_table(struct net_device *netdev,
list_for_each_entry(pnetelem, &smc_pnettable.pnetlist, list) { list_for_each_entry(pnetelem, &smc_pnettable.pnetlist, list) {
if (netdev == pnetelem->ndev) { if (netdev == pnetelem->ndev) {
if (smc_ib_port_active(pnetelem->smcibdev, if (smc_ib_port_active(pnetelem->smcibdev,
pnetelem->ib_port)) { pnetelem->ib_port) &&
!smc_ib_determine_gid(pnetelem->smcibdev,
pnetelem->ib_port, vlan_id,
gid, NULL)) {
*smcibdev = pnetelem->smcibdev; *smcibdev = pnetelem->smcibdev;
*ibport = pnetelem->ib_port; *ibport = pnetelem->ib_port;
} }
...@@ -612,7 +623,8 @@ static void smc_pnet_find_roce_by_table(struct net_device *netdev, ...@@ -612,7 +623,8 @@ static void smc_pnet_find_roce_by_table(struct net_device *netdev,
* ethernet interface. * ethernet interface.
*/ */
void smc_pnet_find_roce_resource(struct sock *sk, void smc_pnet_find_roce_resource(struct sock *sk,
struct smc_ib_device **smcibdev, u8 *ibport) struct smc_ib_device **smcibdev, u8 *ibport,
unsigned short vlan_id, u8 gid[])
{ {
struct dst_entry *dst = sk_dst_get(sk); struct dst_entry *dst = sk_dst_get(sk);
...@@ -625,12 +637,12 @@ void smc_pnet_find_roce_resource(struct sock *sk, ...@@ -625,12 +637,12 @@ void smc_pnet_find_roce_resource(struct sock *sk,
goto out_rel; goto out_rel;
/* if possible, lookup via hardware-defined pnetid */ /* if possible, lookup via hardware-defined pnetid */
smc_pnet_find_roce_by_pnetid(dst->dev, smcibdev, ibport); smc_pnet_find_roce_by_pnetid(dst->dev, smcibdev, ibport, vlan_id, gid);
if (*smcibdev) if (*smcibdev)
goto out_rel; goto out_rel;
/* lookup via SMC PNET table */ /* lookup via SMC PNET table */
smc_pnet_find_roce_by_table(dst->dev, smcibdev, ibport); smc_pnet_find_roce_by_table(dst->dev, smcibdev, ibport, vlan_id, gid);
out_rel: out_rel:
dst_release(dst); dst_release(dst);
......
...@@ -33,7 +33,8 @@ int smc_pnet_init(void) __init; ...@@ -33,7 +33,8 @@ int smc_pnet_init(void) __init;
void smc_pnet_exit(void); void smc_pnet_exit(void);
int smc_pnet_remove_by_ibdev(struct smc_ib_device *ibdev); int smc_pnet_remove_by_ibdev(struct smc_ib_device *ibdev);
void smc_pnet_find_roce_resource(struct sock *sk, void smc_pnet_find_roce_resource(struct sock *sk,
struct smc_ib_device **smcibdev, u8 *ibport); struct smc_ib_device **smcibdev, u8 *ibport,
unsigned short vlan_id, u8 gid[]);
void smc_pnet_find_ism_resource(struct sock *sk, struct smcd_dev **smcismdev); void smc_pnet_find_ism_resource(struct sock *sk, struct smcd_dev **smcismdev);
#endif #endif
...@@ -182,17 +182,14 @@ int smc_wr_tx_get_free_slot(struct smc_link *link, ...@@ -182,17 +182,14 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
if (rc) if (rc)
return rc; return rc;
} else { } else {
struct smc_link_group *lgr;
lgr = smc_get_lgr(link);
rc = wait_event_timeout( rc = wait_event_timeout(
link->wr_tx_wait, link->wr_tx_wait,
list_empty(&lgr->list) || /* lgr terminated */ link->state == SMC_LNK_INACTIVE ||
(smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY), (smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY),
SMC_WR_TX_WAIT_FREE_SLOT_TIME); SMC_WR_TX_WAIT_FREE_SLOT_TIME);
if (!rc) { if (!rc) {
/* timeout - terminate connections */ /* timeout - terminate connections */
smc_lgr_terminate(lgr); smc_lgr_terminate(smc_get_lgr(link));
return -EPIPE; return -EPIPE;
} }
if (idx == link->wr_tx_cnt) if (idx == link->wr_tx_cnt)
......
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