Skip to content

Commit

Permalink
net/smc: {at|de}tach sndbuf to peer DMB if supported
Browse files Browse the repository at this point in the history
If the device used by SMC-D supports merging local sndbuf to peer DMB,
then create sndbuf descriptor and attach it to peer DMB once peer
token is obtained, and detach and free the sndbuf descriptor when the
connection is freed.

Signed-off-by: Wen Gu <guwen@linux.alibaba.com>
Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
Reviewed-and-tested-by: Jan Karcher <jaka@linux.ibm.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Wen Gu authored and Paolo Abeni committed Apr 30, 2024
1 parent 4398888 commit ae2be35
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 1 deletion.
16 changes: 16 additions & 0 deletions net/smc/af_smc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,14 @@ static int smc_connect_ism(struct smc_sock *smc,
}

smc_conn_save_peer_info(smc, aclc);

if (smc_ism_support_dmb_nocopy(smc->conn.lgr->smcd)) {
rc = smcd_buf_attach(smc);
if (rc) {
rc = SMC_CLC_DECL_MEM; /* try to fallback */
goto connect_abort;
}
}
smc_close_init(smc);
smc_rx_init(smc);
smc_tx_init(smc);
Expand Down Expand Up @@ -2540,6 +2548,14 @@ static void smc_listen_work(struct work_struct *work)
mutex_unlock(&smc_server_lgr_pending);
}
smc_conn_save_peer_info(new_smc, cclc);

if (ini->is_smcd &&
smc_ism_support_dmb_nocopy(new_smc->conn.lgr->smcd)) {
rc = smcd_buf_attach(new_smc);
if (rc)
goto out_decl;
}

smc_listen_out_connected(new_smc);
SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk), ini);
goto out_free;
Expand Down
61 changes: 60 additions & 1 deletion net/smc/smc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,20 @@ static void smcr_buf_unuse(struct smc_buf_desc *buf_desc, bool is_rmb,
}
}

static void smcd_buf_detach(struct smc_connection *conn)
{
struct smcd_dev *smcd = conn->lgr->smcd;
u64 peer_token = conn->peer_token;

if (!conn->sndbuf_desc)
return;

smc_ism_detach_dmb(smcd, peer_token);

kfree(conn->sndbuf_desc);
conn->sndbuf_desc = NULL;
}

static void smc_buf_unuse(struct smc_connection *conn,
struct smc_link_group *lgr)
{
Expand Down Expand Up @@ -1192,6 +1206,8 @@ void smc_conn_free(struct smc_connection *conn)
if (lgr->is_smcd) {
if (!list_empty(&lgr->list))
smc_ism_unset_conn(conn);
if (smc_ism_support_dmb_nocopy(lgr->smcd))
smcd_buf_detach(conn);
tasklet_kill(&conn->rx_tsklet);
} else {
smc_cdc_wait_pend_tx_wr(conn);
Expand Down Expand Up @@ -1445,6 +1461,8 @@ static void smc_conn_kill(struct smc_connection *conn, bool soft)
smc_sk_wake_ups(smc);
if (conn->lgr->is_smcd) {
smc_ism_unset_conn(conn);
if (smc_ism_support_dmb_nocopy(conn->lgr->smcd))
smcd_buf_detach(conn);
if (soft)
tasklet_kill(&conn->rx_tsklet);
else
Expand Down Expand Up @@ -2464,12 +2482,18 @@ int smc_buf_create(struct smc_sock *smc, bool is_smcd)
int rc;

/* create send buffer */
if (is_smcd &&
smc_ism_support_dmb_nocopy(smc->conn.lgr->smcd))
goto create_rmb;

rc = __smc_buf_create(smc, is_smcd, false);
if (rc)
return rc;

create_rmb:
/* create rmb */
rc = __smc_buf_create(smc, is_smcd, true);
if (rc) {
if (rc && smc->conn.sndbuf_desc) {
down_write(&smc->conn.lgr->sndbufs_lock);
list_del(&smc->conn.sndbuf_desc->list);
up_write(&smc->conn.lgr->sndbufs_lock);
Expand All @@ -2479,6 +2503,41 @@ int smc_buf_create(struct smc_sock *smc, bool is_smcd)
return rc;
}

int smcd_buf_attach(struct smc_sock *smc)
{
struct smc_connection *conn = &smc->conn;
struct smcd_dev *smcd = conn->lgr->smcd;
u64 peer_token = conn->peer_token;
struct smc_buf_desc *buf_desc;
int rc;

buf_desc = kzalloc(sizeof(*buf_desc), GFP_KERNEL);
if (!buf_desc)
return -ENOMEM;

/* The ghost sndbuf_desc describes the same memory region as
* peer RMB. Its lifecycle is consistent with the connection's
* and it will be freed with the connections instead of the
* link group.
*/
rc = smc_ism_attach_dmb(smcd, peer_token, buf_desc);
if (rc)
goto free;

smc->sk.sk_sndbuf = buf_desc->len;
buf_desc->cpu_addr =
(u8 *)buf_desc->cpu_addr + sizeof(struct smcd_cdc_msg);
buf_desc->len -= sizeof(struct smcd_cdc_msg);
conn->sndbuf_desc = buf_desc;
conn->sndbuf_desc->used = 1;
atomic_set(&conn->sndbuf_space, conn->sndbuf_desc->len);
return 0;

free:
kfree(buf_desc);
return rc;
}

static inline int smc_rmb_reserve_rtoken_idx(struct smc_link_group *lgr)
{
int i;
Expand Down
1 change: 1 addition & 0 deletions net/smc/smc_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, struct smcd_gid *peer_gid,
void smc_smcd_terminate_all(struct smcd_dev *dev);
void smc_smcr_terminate_all(struct smc_ib_device *smcibdev);
int smc_buf_create(struct smc_sock *smc, bool is_smcd);
int smcd_buf_attach(struct smc_sock *smc);
int smc_uncompress_bufsize(u8 compressed);
int smc_rmb_rtoken_handling(struct smc_connection *conn, struct smc_link *link,
struct smc_clc_msg_accept_confirm *clc);
Expand Down

0 comments on commit ae2be35

Please sign in to comment.