Merge branch 'smc-fixes'
Ursula Braun says: ==================== net/smc: fixes 2018-11-12 here is V4 of some net/smc fixes in different areas for the net tree. v1->v2: do not define 8-byte alignment for union smcd_cdc_cursor in patch 4/5 "net/smc: atomic SMCD cursor handling" v2->v3: stay with 8-byte alignment for union smcd_cdc_cursor in patch 4/5 "net/smc: atomic SMCD cursor handling", but get rid of __packed for struct smcd_cdc_msg v3->v4: get rid of another __packed for struct smc_cdc_msg in patch 4/5 "net/smc: atomic SMCD cursor handling" ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
395048ebd4
|
@ -127,6 +127,8 @@ static int smc_release(struct socket *sock)
|
||||||
smc = smc_sk(sk);
|
smc = smc_sk(sk);
|
||||||
|
|
||||||
/* cleanup for a dangling non-blocking connect */
|
/* cleanup for a dangling non-blocking connect */
|
||||||
|
if (smc->connect_info && sk->sk_state == SMC_INIT)
|
||||||
|
tcp_abort(smc->clcsock->sk, ECONNABORTED);
|
||||||
flush_work(&smc->connect_work);
|
flush_work(&smc->connect_work);
|
||||||
kfree(smc->connect_info);
|
kfree(smc->connect_info);
|
||||||
smc->connect_info = NULL;
|
smc->connect_info = NULL;
|
||||||
|
@ -547,7 +549,8 @@ static int smc_connect_rdma(struct smc_sock *smc,
|
||||||
|
|
||||||
mutex_lock(&smc_create_lgr_pending);
|
mutex_lock(&smc_create_lgr_pending);
|
||||||
local_contact = smc_conn_create(smc, false, aclc->hdr.flag, ibdev,
|
local_contact = smc_conn_create(smc, false, aclc->hdr.flag, ibdev,
|
||||||
ibport, &aclc->lcl, NULL, 0);
|
ibport, ntoh24(aclc->qpn), &aclc->lcl,
|
||||||
|
NULL, 0);
|
||||||
if (local_contact < 0) {
|
if (local_contact < 0) {
|
||||||
if (local_contact == -ENOMEM)
|
if (local_contact == -ENOMEM)
|
||||||
reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/
|
reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/
|
||||||
|
@ -618,7 +621,7 @@ static int smc_connect_ism(struct smc_sock *smc,
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
mutex_lock(&smc_create_lgr_pending);
|
mutex_lock(&smc_create_lgr_pending);
|
||||||
local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0,
|
local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0, 0,
|
||||||
NULL, ismdev, aclc->gid);
|
NULL, ismdev, aclc->gid);
|
||||||
if (local_contact < 0)
|
if (local_contact < 0)
|
||||||
return smc_connect_abort(smc, SMC_CLC_DECL_MEM, 0);
|
return smc_connect_abort(smc, SMC_CLC_DECL_MEM, 0);
|
||||||
|
@ -1083,7 +1086,7 @@ static int smc_listen_rdma_init(struct smc_sock *new_smc,
|
||||||
int *local_contact)
|
int *local_contact)
|
||||||
{
|
{
|
||||||
/* allocate connection / link group */
|
/* allocate connection / link group */
|
||||||
*local_contact = smc_conn_create(new_smc, false, 0, ibdev, ibport,
|
*local_contact = smc_conn_create(new_smc, false, 0, ibdev, ibport, 0,
|
||||||
&pclc->lcl, NULL, 0);
|
&pclc->lcl, NULL, 0);
|
||||||
if (*local_contact < 0) {
|
if (*local_contact < 0) {
|
||||||
if (*local_contact == -ENOMEM)
|
if (*local_contact == -ENOMEM)
|
||||||
|
@ -1107,7 +1110,7 @@ static int smc_listen_ism_init(struct smc_sock *new_smc,
|
||||||
struct smc_clc_msg_smcd *pclc_smcd;
|
struct smc_clc_msg_smcd *pclc_smcd;
|
||||||
|
|
||||||
pclc_smcd = smc_get_clc_msg_smcd(pclc);
|
pclc_smcd = smc_get_clc_msg_smcd(pclc);
|
||||||
*local_contact = smc_conn_create(new_smc, true, 0, NULL, 0, NULL,
|
*local_contact = smc_conn_create(new_smc, true, 0, NULL, 0, 0, NULL,
|
||||||
ismdev, pclc_smcd->gid);
|
ismdev, pclc_smcd->gid);
|
||||||
if (*local_contact < 0) {
|
if (*local_contact < 0) {
|
||||||
if (*local_contact == -ENOMEM)
|
if (*local_contact == -ENOMEM)
|
||||||
|
|
|
@ -81,7 +81,7 @@ static inline void smc_cdc_add_pending_send(struct smc_connection *conn,
|
||||||
sizeof(struct smc_cdc_msg) > SMC_WR_BUF_SIZE,
|
sizeof(struct smc_cdc_msg) > SMC_WR_BUF_SIZE,
|
||||||
"must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_cdc_msg)");
|
"must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_cdc_msg)");
|
||||||
BUILD_BUG_ON_MSG(
|
BUILD_BUG_ON_MSG(
|
||||||
sizeof(struct smc_cdc_msg) != SMC_WR_TX_SIZE,
|
offsetofend(struct smc_cdc_msg, reserved) > SMC_WR_TX_SIZE,
|
||||||
"must adapt SMC_WR_TX_SIZE to sizeof(struct smc_cdc_msg); if not all smc_wr upper layer protocols use the same message size any more, must start to set link->wr_tx_sges[i].length on each individual smc_wr_tx_send()");
|
"must adapt SMC_WR_TX_SIZE to sizeof(struct smc_cdc_msg); if not all smc_wr upper layer protocols use the same message size any more, must start to set link->wr_tx_sges[i].length on each individual smc_wr_tx_send()");
|
||||||
BUILD_BUG_ON_MSG(
|
BUILD_BUG_ON_MSG(
|
||||||
sizeof(struct smc_cdc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE,
|
sizeof(struct smc_cdc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE,
|
||||||
|
@ -177,23 +177,24 @@ void smc_cdc_tx_dismiss_slots(struct smc_connection *conn)
|
||||||
int smcd_cdc_msg_send(struct smc_connection *conn)
|
int smcd_cdc_msg_send(struct smc_connection *conn)
|
||||||
{
|
{
|
||||||
struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
|
struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
|
||||||
|
union smc_host_cursor curs;
|
||||||
struct smcd_cdc_msg cdc;
|
struct smcd_cdc_msg cdc;
|
||||||
int rc, diff;
|
int rc, diff;
|
||||||
|
|
||||||
memset(&cdc, 0, sizeof(cdc));
|
memset(&cdc, 0, sizeof(cdc));
|
||||||
cdc.common.type = SMC_CDC_MSG_TYPE;
|
cdc.common.type = SMC_CDC_MSG_TYPE;
|
||||||
cdc.prod_wrap = conn->local_tx_ctrl.prod.wrap;
|
curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.prod.acurs);
|
||||||
cdc.prod_count = conn->local_tx_ctrl.prod.count;
|
cdc.prod.wrap = curs.wrap;
|
||||||
|
cdc.prod.count = curs.count;
|
||||||
cdc.cons_wrap = conn->local_tx_ctrl.cons.wrap;
|
curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.cons.acurs);
|
||||||
cdc.cons_count = conn->local_tx_ctrl.cons.count;
|
cdc.cons.wrap = curs.wrap;
|
||||||
cdc.prod_flags = conn->local_tx_ctrl.prod_flags;
|
cdc.cons.count = curs.count;
|
||||||
cdc.conn_state_flags = conn->local_tx_ctrl.conn_state_flags;
|
cdc.cons.prod_flags = conn->local_tx_ctrl.prod_flags;
|
||||||
|
cdc.cons.conn_state_flags = conn->local_tx_ctrl.conn_state_flags;
|
||||||
rc = smcd_tx_ism_write(conn, &cdc, sizeof(cdc), 0, 1);
|
rc = smcd_tx_ism_write(conn, &cdc, sizeof(cdc), 0, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
smc_curs_copy(&conn->rx_curs_confirmed, &conn->local_tx_ctrl.cons,
|
smc_curs_copy(&conn->rx_curs_confirmed, &curs, conn);
|
||||||
conn);
|
|
||||||
/* Calculate transmitted data and increment free send buffer space */
|
/* Calculate transmitted data and increment free send buffer space */
|
||||||
diff = smc_curs_diff(conn->sndbuf_desc->len, &conn->tx_curs_fin,
|
diff = smc_curs_diff(conn->sndbuf_desc->len, &conn->tx_curs_fin,
|
||||||
&conn->tx_curs_sent);
|
&conn->tx_curs_sent);
|
||||||
|
@ -331,13 +332,16 @@ static void smc_cdc_msg_recv(struct smc_sock *smc, struct smc_cdc_msg *cdc)
|
||||||
static void smcd_cdc_rx_tsklet(unsigned long data)
|
static void smcd_cdc_rx_tsklet(unsigned long data)
|
||||||
{
|
{
|
||||||
struct smc_connection *conn = (struct smc_connection *)data;
|
struct smc_connection *conn = (struct smc_connection *)data;
|
||||||
|
struct smcd_cdc_msg *data_cdc;
|
||||||
struct smcd_cdc_msg cdc;
|
struct smcd_cdc_msg cdc;
|
||||||
struct smc_sock *smc;
|
struct smc_sock *smc;
|
||||||
|
|
||||||
if (!conn)
|
if (!conn)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(&cdc, conn->rmb_desc->cpu_addr, sizeof(cdc));
|
data_cdc = (struct smcd_cdc_msg *)conn->rmb_desc->cpu_addr;
|
||||||
|
smcd_curs_copy(&cdc.prod, &data_cdc->prod, conn);
|
||||||
|
smcd_curs_copy(&cdc.cons, &data_cdc->cons, conn);
|
||||||
smc = container_of(conn, struct smc_sock, conn);
|
smc = container_of(conn, struct smc_sock, conn);
|
||||||
smc_cdc_msg_recv(smc, (struct smc_cdc_msg *)&cdc);
|
smc_cdc_msg_recv(smc, (struct smc_cdc_msg *)&cdc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,21 +48,31 @@ struct smc_cdc_msg {
|
||||||
struct smc_cdc_producer_flags prod_flags;
|
struct smc_cdc_producer_flags prod_flags;
|
||||||
struct smc_cdc_conn_state_flags conn_state_flags;
|
struct smc_cdc_conn_state_flags conn_state_flags;
|
||||||
u8 reserved[18];
|
u8 reserved[18];
|
||||||
} __packed; /* format defined in RFC7609 */
|
};
|
||||||
|
|
||||||
|
/* SMC-D cursor format */
|
||||||
|
union smcd_cdc_cursor {
|
||||||
|
struct {
|
||||||
|
u16 wrap;
|
||||||
|
u32 count;
|
||||||
|
struct smc_cdc_producer_flags prod_flags;
|
||||||
|
struct smc_cdc_conn_state_flags conn_state_flags;
|
||||||
|
} __packed;
|
||||||
|
#ifdef KERNEL_HAS_ATOMIC64
|
||||||
|
atomic64_t acurs; /* for atomic processing */
|
||||||
|
#else
|
||||||
|
u64 acurs; /* for atomic processing */
|
||||||
|
#endif
|
||||||
|
} __aligned(8);
|
||||||
|
|
||||||
/* CDC message for SMC-D */
|
/* CDC message for SMC-D */
|
||||||
struct smcd_cdc_msg {
|
struct smcd_cdc_msg {
|
||||||
struct smc_wr_rx_hdr common; /* Type = 0xFE */
|
struct smc_wr_rx_hdr common; /* Type = 0xFE */
|
||||||
u8 res1[7];
|
u8 res1[7];
|
||||||
u16 prod_wrap;
|
union smcd_cdc_cursor prod;
|
||||||
u32 prod_count;
|
union smcd_cdc_cursor cons;
|
||||||
u8 res2[2];
|
|
||||||
u16 cons_wrap;
|
|
||||||
u32 cons_count;
|
|
||||||
struct smc_cdc_producer_flags prod_flags;
|
|
||||||
struct smc_cdc_conn_state_flags conn_state_flags;
|
|
||||||
u8 res3[8];
|
u8 res3[8];
|
||||||
} __packed;
|
} __aligned(8);
|
||||||
|
|
||||||
static inline bool smc_cdc_rxed_any_close(struct smc_connection *conn)
|
static inline bool smc_cdc_rxed_any_close(struct smc_connection *conn)
|
||||||
{
|
{
|
||||||
|
@ -135,6 +145,21 @@ static inline void smc_curs_copy_net(union smc_cdc_cursor *tgt,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt,
|
||||||
|
union smcd_cdc_cursor *src,
|
||||||
|
struct smc_connection *conn)
|
||||||
|
{
|
||||||
|
#ifndef KERNEL_HAS_ATOMIC64
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&conn->acurs_lock, flags);
|
||||||
|
tgt->acurs = src->acurs;
|
||||||
|
spin_unlock_irqrestore(&conn->acurs_lock, flags);
|
||||||
|
#else
|
||||||
|
atomic64_set(&tgt->acurs, atomic64_read(&src->acurs));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* calculate cursor difference between old and new, where old <= new */
|
/* calculate cursor difference between old and new, where old <= new */
|
||||||
static inline int smc_curs_diff(unsigned int size,
|
static inline int smc_curs_diff(unsigned int size,
|
||||||
union smc_host_cursor *old,
|
union smc_host_cursor *old,
|
||||||
|
@ -222,12 +247,17 @@ static inline void smcr_cdc_msg_to_host(struct smc_host_cdc_msg *local,
|
||||||
static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local,
|
static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local,
|
||||||
struct smcd_cdc_msg *peer)
|
struct smcd_cdc_msg *peer)
|
||||||
{
|
{
|
||||||
local->prod.wrap = peer->prod_wrap;
|
union smc_host_cursor temp;
|
||||||
local->prod.count = peer->prod_count;
|
|
||||||
local->cons.wrap = peer->cons_wrap;
|
temp.wrap = peer->prod.wrap;
|
||||||
local->cons.count = peer->cons_count;
|
temp.count = peer->prod.count;
|
||||||
local->prod_flags = peer->prod_flags;
|
atomic64_set(&local->prod.acurs, atomic64_read(&temp.acurs));
|
||||||
local->conn_state_flags = peer->conn_state_flags;
|
|
||||||
|
temp.wrap = peer->cons.wrap;
|
||||||
|
temp.count = peer->cons.count;
|
||||||
|
atomic64_set(&local->cons.acurs, atomic64_read(&temp.acurs));
|
||||||
|
local->prod_flags = peer->cons.prod_flags;
|
||||||
|
local->conn_state_flags = peer->cons.conn_state_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
|
static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
|
||||||
|
|
|
@ -184,6 +184,8 @@ free:
|
||||||
|
|
||||||
if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE)
|
if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE)
|
||||||
smc_llc_link_inactive(lnk);
|
smc_llc_link_inactive(lnk);
|
||||||
|
if (lgr->is_smcd)
|
||||||
|
smc_ism_signal_shutdown(lgr);
|
||||||
smc_lgr_free(lgr);
|
smc_lgr_free(lgr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -485,7 +487,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when SMC-D device is terminated or peer is lost */
|
/* Called when SMC-D device is terminated or peer is lost */
|
||||||
void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
|
void smc_smcd_terminate(struct smcd_dev *dev, u64 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);
|
||||||
|
@ -495,7 +497,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
|
||||||
list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) {
|
list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) {
|
||||||
if (lgr->is_smcd && lgr->smcd == dev &&
|
if (lgr->is_smcd && lgr->smcd == dev &&
|
||||||
(!peer_gid || lgr->peer_gid == peer_gid) &&
|
(!peer_gid || lgr->peer_gid == peer_gid) &&
|
||||||
!list_empty(&lgr->list)) {
|
(vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
|
||||||
__smc_lgr_terminate(lgr);
|
__smc_lgr_terminate(lgr);
|
||||||
list_move(&lgr->list, &lgr_free_list);
|
list_move(&lgr->list, &lgr_free_list);
|
||||||
}
|
}
|
||||||
|
@ -506,6 +508,8 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
|
||||||
list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
|
list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
|
||||||
list_del_init(&lgr->list);
|
list_del_init(&lgr->list);
|
||||||
cancel_delayed_work_sync(&lgr->free_work);
|
cancel_delayed_work_sync(&lgr->free_work);
|
||||||
|
if (!peer_gid && vlan == VLAN_VID_MASK) /* dev terminated? */
|
||||||
|
smc_ism_signal_shutdown(lgr);
|
||||||
smc_lgr_free(lgr);
|
smc_lgr_free(lgr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,7 +563,7 @@ out:
|
||||||
|
|
||||||
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, u32 clcqpn)
|
||||||
{
|
{
|
||||||
return !memcmp(lgr->peer_systemid, lcl->id_for_peer,
|
return !memcmp(lgr->peer_systemid, lcl->id_for_peer,
|
||||||
SMC_SYSTEMID_LEN) &&
|
SMC_SYSTEMID_LEN) &&
|
||||||
|
@ -567,7 +571,9 @@ static bool smcr_lgr_match(struct smc_link_group *lgr,
|
||||||
SMC_GID_SIZE) &&
|
SMC_GID_SIZE) &&
|
||||||
!memcmp(lgr->lnk[SMC_SINGLE_LINK].peer_mac, lcl->mac,
|
!memcmp(lgr->lnk[SMC_SINGLE_LINK].peer_mac, lcl->mac,
|
||||||
sizeof(lcl->mac)) &&
|
sizeof(lcl->mac)) &&
|
||||||
lgr->role == role;
|
lgr->role == role &&
|
||||||
|
(lgr->role == SMC_SERV ||
|
||||||
|
lgr->lnk[SMC_SINGLE_LINK].peer_qpn == clcqpn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool smcd_lgr_match(struct smc_link_group *lgr,
|
static bool smcd_lgr_match(struct smc_link_group *lgr,
|
||||||
|
@ -578,7 +584,7 @@ static bool smcd_lgr_match(struct smc_link_group *lgr,
|
||||||
|
|
||||||
/* create a new SMC connection (and a new link group if necessary) */
|
/* create a new SMC connection (and a new link group if necessary) */
|
||||||
int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
|
int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
|
||||||
struct smc_ib_device *smcibdev, u8 ibport,
|
struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn,
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -603,7 +609,7 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
|
||||||
list_for_each_entry(lgr, &smc_lgr_list.list, list) {
|
list_for_each_entry(lgr, &smc_lgr_list.list, list) {
|
||||||
write_lock_bh(&lgr->conns_lock);
|
write_lock_bh(&lgr->conns_lock);
|
||||||
if ((is_smcd ? smcd_lgr_match(lgr, smcd, peer_gid) :
|
if ((is_smcd ? smcd_lgr_match(lgr, smcd, peer_gid) :
|
||||||
smcr_lgr_match(lgr, lcl, role)) &&
|
smcr_lgr_match(lgr, lcl, role, clcqpn)) &&
|
||||||
!lgr->sync_err &&
|
!lgr->sync_err &&
|
||||||
lgr->vlan_id == vlan_id &&
|
lgr->vlan_id == vlan_id &&
|
||||||
(role == SMC_CLNT ||
|
(role == SMC_CLNT ||
|
||||||
|
@ -1024,6 +1030,8 @@ void smc_core_exit(void)
|
||||||
smc_llc_link_inactive(lnk);
|
smc_llc_link_inactive(lnk);
|
||||||
}
|
}
|
||||||
cancel_delayed_work_sync(&lgr->free_work);
|
cancel_delayed_work_sync(&lgr->free_work);
|
||||||
|
if (lgr->is_smcd)
|
||||||
|
smc_ism_signal_shutdown(lgr);
|
||||||
smc_lgr_free(lgr); /* free link group */
|
smc_lgr_free(lgr); /* free link group */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,7 +247,8 @@ void smc_lgr_free(struct smc_link_group *lgr);
|
||||||
void smc_lgr_forget(struct smc_link_group *lgr);
|
void smc_lgr_forget(struct smc_link_group *lgr);
|
||||||
void smc_lgr_terminate(struct smc_link_group *lgr);
|
void smc_lgr_terminate(struct smc_link_group *lgr);
|
||||||
void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport);
|
void smc_port_terminate(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, u64 peer_gid,
|
||||||
|
unsigned short vlan);
|
||||||
int smc_buf_create(struct smc_sock *smc, bool is_smcd);
|
int smc_buf_create(struct smc_sock *smc, bool is_smcd);
|
||||||
int smc_uncompress_bufsize(u8 compressed);
|
int smc_uncompress_bufsize(u8 compressed);
|
||||||
int smc_rmb_rtoken_handling(struct smc_connection *conn,
|
int smc_rmb_rtoken_handling(struct smc_connection *conn,
|
||||||
|
@ -262,7 +263,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id);
|
||||||
|
|
||||||
void smc_conn_free(struct smc_connection *conn);
|
void smc_conn_free(struct smc_connection *conn);
|
||||||
int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
|
int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
|
||||||
struct smc_ib_device *smcibdev, u8 ibport,
|
struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn,
|
||||||
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);
|
||||||
|
|
|
@ -187,22 +187,28 @@ struct smc_ism_event_work {
|
||||||
#define ISM_EVENT_REQUEST 0x0001
|
#define ISM_EVENT_REQUEST 0x0001
|
||||||
#define ISM_EVENT_RESPONSE 0x0002
|
#define ISM_EVENT_RESPONSE 0x0002
|
||||||
#define ISM_EVENT_REQUEST_IR 0x00000001
|
#define ISM_EVENT_REQUEST_IR 0x00000001
|
||||||
|
#define ISM_EVENT_CODE_SHUTDOWN 0x80
|
||||||
#define ISM_EVENT_CODE_TESTLINK 0x83
|
#define ISM_EVENT_CODE_TESTLINK 0x83
|
||||||
|
|
||||||
|
union smcd_sw_event_info {
|
||||||
|
u64 info;
|
||||||
|
struct {
|
||||||
|
u8 uid[SMC_LGR_ID_SIZE];
|
||||||
|
unsigned short vlan_id;
|
||||||
|
u16 code;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
|
static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
|
||||||
{
|
{
|
||||||
union {
|
union smcd_sw_event_info ev_info;
|
||||||
u64 info;
|
|
||||||
struct {
|
|
||||||
u32 uid;
|
|
||||||
unsigned short vlanid;
|
|
||||||
u16 code;
|
|
||||||
};
|
|
||||||
} ev_info;
|
|
||||||
|
|
||||||
switch (wrk->event.code) {
|
|
||||||
case ISM_EVENT_CODE_TESTLINK: /* Activity timer */
|
|
||||||
ev_info.info = wrk->event.info;
|
ev_info.info = wrk->event.info;
|
||||||
|
switch (wrk->event.code) {
|
||||||
|
case ISM_EVENT_CODE_SHUTDOWN: /* Peer shut down DMBs */
|
||||||
|
smc_smcd_terminate(wrk->smcd, wrk->event.tok, ev_info.vlan_id);
|
||||||
|
break;
|
||||||
|
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,
|
||||||
|
@ -215,6 +221,21 @@ static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int smc_ism_signal_shutdown(struct smc_link_group *lgr)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
union smcd_sw_event_info ev_info;
|
||||||
|
|
||||||
|
memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
|
||||||
|
ev_info.vlan_id = lgr->vlan_id;
|
||||||
|
ev_info.code = ISM_EVENT_REQUEST;
|
||||||
|
rc = lgr->smcd->ops->signal_event(lgr->smcd, lgr->peer_gid,
|
||||||
|
ISM_EVENT_REQUEST_IR,
|
||||||
|
ISM_EVENT_CODE_SHUTDOWN,
|
||||||
|
ev_info.info);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* worker for SMC-D events */
|
/* worker for SMC-D events */
|
||||||
static void smc_ism_event_work(struct work_struct *work)
|
static void smc_ism_event_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
|
@ -223,7 +244,7 @@ static void smc_ism_event_work(struct work_struct *work)
|
||||||
|
|
||||||
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);
|
smc_smcd_terminate(wrk->smcd, wrk->event.tok, VLAN_VID_MASK);
|
||||||
break;
|
break;
|
||||||
case ISM_EVENT_DMB:
|
case ISM_EVENT_DMB:
|
||||||
break;
|
break;
|
||||||
|
@ -289,7 +310,7 @@ void smcd_unregister_dev(struct smcd_dev *smcd)
|
||||||
spin_unlock(&smcd_dev_list.lock);
|
spin_unlock(&smcd_dev_list.lock);
|
||||||
flush_workqueue(smcd->event_wq);
|
flush_workqueue(smcd->event_wq);
|
||||||
destroy_workqueue(smcd->event_wq);
|
destroy_workqueue(smcd->event_wq);
|
||||||
smc_smcd_terminate(smcd, 0);
|
smc_smcd_terminate(smcd, 0, VLAN_VID_MASK);
|
||||||
|
|
||||||
device_del(&smcd->dev);
|
device_del(&smcd->dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,4 +45,5 @@ int smc_ism_register_dmb(struct smc_link_group *lgr, int buf_size,
|
||||||
int smc_ism_unregister_dmb(struct smcd_dev *dev, struct smc_buf_desc *dmb_desc);
|
int smc_ism_unregister_dmb(struct smcd_dev *dev, struct smc_buf_desc *dmb_desc);
|
||||||
int smc_ism_write(struct smcd_dev *dev, const struct smc_ism_position *pos,
|
int smc_ism_write(struct smcd_dev *dev, const struct smc_ism_position *pos,
|
||||||
void *data, size_t len);
|
void *data, size_t len);
|
||||||
|
int smc_ism_signal_shutdown(struct smc_link_group *lgr);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -215,12 +215,14 @@ int smc_wr_tx_put_slot(struct smc_link *link,
|
||||||
|
|
||||||
pend = container_of(wr_pend_priv, struct smc_wr_tx_pend, priv);
|
pend = container_of(wr_pend_priv, struct smc_wr_tx_pend, priv);
|
||||||
if (pend->idx < link->wr_tx_cnt) {
|
if (pend->idx < link->wr_tx_cnt) {
|
||||||
|
u32 idx = pend->idx;
|
||||||
|
|
||||||
/* clear the full struct smc_wr_tx_pend including .priv */
|
/* clear the full struct smc_wr_tx_pend including .priv */
|
||||||
memset(&link->wr_tx_pends[pend->idx], 0,
|
memset(&link->wr_tx_pends[pend->idx], 0,
|
||||||
sizeof(link->wr_tx_pends[pend->idx]));
|
sizeof(link->wr_tx_pends[pend->idx]));
|
||||||
memset(&link->wr_tx_bufs[pend->idx], 0,
|
memset(&link->wr_tx_bufs[pend->idx], 0,
|
||||||
sizeof(link->wr_tx_bufs[pend->idx]));
|
sizeof(link->wr_tx_bufs[pend->idx]));
|
||||||
test_and_clear_bit(pend->idx, link->wr_tx_mask);
|
test_and_clear_bit(idx, link->wr_tx_mask);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче