From 22e95a966357e9879554b61c744c39fbd16daeab Mon Sep 17 00:00:00 2001 From: Litao Jiao Date: Tue, 23 May 2023 12:01:40 +0800 Subject: [PATCH 1/2] net/smc: remove redundant dma sync ops mainline inclusion from mainline-v6.0-rc1 commit 6d52e2de6415b7a035b3e8dc4ccffd0da25bbfb9 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I77IM8 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/smc?id=6d52e2de6415b7a035b3e8dc4ccffd0da25bbfb9 -------------------------------- smc_ib_sync_sg_for_cpu/device are the ops used for dma memory cache consistency. Smc sndbufs are dma buffers, where CPU writes data to it and PCIE device reads data from it. So for sndbufs, smc_ib_sync_sg_for_device is needed and smc_ib_sync_sg_for_cpu is redundant as PCIE device will not write the buffers. Smc rmbs are dma buffers, where PCIE device write data to it and CPU read data from it. So for rmbs, smc_ib_sync_sg_for_cpu is needed and smc_ib_sync_sg_for_device is redundant as CPU will not write the buffers. Signed-off-by: Guangguan Wang Signed-off-by: David S. Miller Signed-off-by: Litao Jiao --- net/smc/af_smc.c | 2 -- net/smc/smc_core.c | 21 --------------------- net/smc/smc_core.h | 2 -- net/smc/smc_rx.c | 2 -- net/smc/smc_tx.c | 1 - 5 files changed, 28 deletions(-) diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 41cbc7c89c9d..a13cc62424de 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -814,7 +814,6 @@ static int smc_connect_rdma(struct smc_sock *smc, goto connect_abort; } } - smc_rmb_sync_sg_for_device(&smc->conn); reason_code = smc_clc_send_confirm(smc, ini->first_contact_local, SMC_V1); @@ -1598,7 +1597,6 @@ static int smc_listen_rdma_reg(struct smc_sock *new_smc, bool local_first) if (smcr_lgr_reg_rmbs(conn->lnk, conn->rmb_desc)) return SMC_CLC_DECL_ERR_REGRMB; } - smc_rmb_sync_sg_for_device(&new_smc->conn); return 0; } diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index bf485a2017a4..9372bde65f87 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -1729,13 +1729,6 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb) return 0; } -void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn) -{ - if (!conn->lgr || conn->lgr->is_smcd || !smc_link_active(conn->lnk)) - return; - smc_ib_sync_sg_for_cpu(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE); -} - void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn) { if (!conn->lgr || conn->lgr->is_smcd || !smc_link_active(conn->lnk)) @@ -1757,20 +1750,6 @@ void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn) } } -void smc_rmb_sync_sg_for_device(struct smc_connection *conn) -{ - int i; - - if (!conn->lgr || conn->lgr->is_smcd) - return; - for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { - if (!smc_link_active(&conn->lgr->lnk[i])) - continue; - smc_ib_sync_sg_for_device(&conn->lgr->lnk[i], conn->rmb_desc, - DMA_FROM_DEVICE); - } -} - /* create the send and receive buffer for an SMC socket; * receive buffers are called RMBs; * (even though the SMC protocol allows more than one RMB-element per RMB, diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h index 9364d0f35cce..75fb5ea9cfae 100644 --- a/net/smc/smc_core.h +++ b/net/smc/smc_core.h @@ -392,10 +392,8 @@ void smc_rtoken_set(struct smc_link_group *lgr, int link_idx, int link_idx_new, __be32 nw_rkey_known, __be64 nw_vaddr, __be32 nw_rkey); void smc_rtoken_set2(struct smc_link_group *lgr, int rtok_idx, int link_id, __be64 nw_vaddr, __be32 nw_rkey); -void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn); void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn); void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn); -void smc_rmb_sync_sg_for_device(struct smc_connection *conn); int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini); void smc_conn_free(struct smc_connection *conn); diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c index 7f7e983e42b1..4cc750916340 100644 --- a/net/smc/smc_rx.c +++ b/net/smc/smc_rx.c @@ -404,7 +404,6 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, if (rc < 0) { if (!read_done) read_done = -EFAULT; - smc_rmb_sync_sg_for_device(conn); goto out; } } @@ -418,7 +417,6 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, chunk_len_sum += chunk_len; chunk_off = 0; /* modulo offset in recv ring buffer */ } - smc_rmb_sync_sg_for_device(conn); /* update cursors */ if (!(flags & MSG_PEEK)) { diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c index 52ef1fca0b60..473adb269897 100644 --- a/net/smc/smc_tx.c +++ b/net/smc/smc_tx.c @@ -188,7 +188,6 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len) tx_cnt_prep); chunk_len_sum = chunk_len; chunk_off = tx_cnt_prep; - smc_sndbuf_sync_sg_for_cpu(conn); for (chunk = 0; chunk < 2; chunk++) { rc = memcpy_from_msg(sndbuf_base + chunk_off, msg, chunk_len); -- Gitee From 57f3478342d6665bc5875c9f8cc7c6f288ae0cb7 Mon Sep 17 00:00:00 2001 From: Litao Jiao Date: Tue, 23 May 2023 15:07:05 +0800 Subject: [PATCH 2/2] net/smc: optimize for smc_sndbuf_sync_sg_for_device and smc_rmb_sync_sg_for_cpu mainline inclusion from mainline-v6.0-rc1 commit 0ef69e788411cba2af017db731a9fc62d255e9ac category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I77IM8 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/smc?id=0ef69e788411cba2af017db731a9fc62d255e9ac -------------------------------- Some CPU, such as Xeon, can guarantee DMA cache coherency. So it is no need to use dma sync APIs to flush cache on such CPUs. In order to avoid calling dma sync APIs on the IO path, use the dma_need_sync to check whether smc_buf_desc needs dma sync when creating smc_buf_desc. Signed-off-by: Guangguan Wang Signed-off-by: David S. Miller Signed-off-by: Litao Jiao --- net/smc/smc_core.c | 8 ++++++++ net/smc/smc_core.h | 1 + net/smc/smc_ib.c | 29 +++++++++++++++++++++++++++++ net/smc/smc_ib.h | 2 ++ 4 files changed, 40 insertions(+) diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index 9372bde65f87..54ad1b22cebf 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -1453,6 +1453,9 @@ static int smcr_buf_map_link(struct smc_buf_desc *buf_desc, bool is_rmb, goto free_table; } + buf_desc->is_dma_need_sync |= + smc_ib_is_sg_need_sync(lnk, buf_desc) << lnk->link_idx; + /* create a new memory region for the RMB */ if (is_rmb) { rc = smc_ib_get_memory_region(lnk->roce_pd, @@ -1681,6 +1684,7 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb) /* check for reusable slot in the link group */ buf_desc = smc_buf_get_slot(bufsize_short, lock, buf_list); if (buf_desc) { + buf_desc->is_dma_need_sync = 0; memset(buf_desc->cpu_addr, 0, bufsize); break; /* found reusable slot */ } @@ -1731,6 +1735,8 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb) void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn) { + if (!conn->sndbuf_desc->is_dma_need_sync) + return; if (!conn->lgr || conn->lgr->is_smcd || !smc_link_active(conn->lnk)) return; smc_ib_sync_sg_for_device(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE); @@ -1740,6 +1746,8 @@ void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn) { int i; + if (!conn->rmb_desc->is_dma_need_sync) + return; if (!conn->lgr || conn->lgr->is_smcd) return; for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h index 75fb5ea9cfae..07b62e62a46b 100644 --- a/net/smc/smc_core.h +++ b/net/smc/smc_core.h @@ -162,6 +162,7 @@ struct smc_buf_desc { /* mem region registered */ u8 is_map_ib[SMC_LINKS_PER_LGR_MAX]; /* mem region mapped to lnk */ + u8 is_dma_need_sync; u8 is_reg_err; /* buffer registration err */ }; diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c index f1ffbd414602..21c673b34ad5 100644 --- a/net/smc/smc_ib.c +++ b/net/smc/smc_ib.c @@ -428,6 +428,29 @@ int smc_ib_get_memory_region(struct ib_pd *pd, int access_flags, return 0; } +bool smc_ib_is_sg_need_sync(struct smc_link *lnk, + struct smc_buf_desc *buf_slot) +{ + struct scatterlist *sg; + unsigned int i; + bool ret = false; + + /* for now there is just one DMA address */ + for_each_sg(buf_slot->sgt[lnk->link_idx].sgl, sg, + buf_slot->sgt[lnk->link_idx].nents, i) { + if (!sg_dma_len(sg)) + break; + if (dma_need_sync(lnk->smcibdev->ibdev->dma_device, + sg_dma_address(sg))) { + ret = true; + goto out; + } + } + +out: + return ret; +} + /* synchronize buffer usage for cpu access */ void smc_ib_sync_sg_for_cpu(struct smc_link *lnk, struct smc_buf_desc *buf_slot, @@ -436,6 +459,9 @@ void smc_ib_sync_sg_for_cpu(struct smc_link *lnk, struct scatterlist *sg; unsigned int i; + if (!(buf_slot->is_dma_need_sync & (1U << lnk->link_idx))) + return; + /* for now there is just one DMA address */ for_each_sg(buf_slot->sgt[lnk->link_idx].sgl, sg, buf_slot->sgt[lnk->link_idx].nents, i) { @@ -456,6 +482,9 @@ void smc_ib_sync_sg_for_device(struct smc_link *lnk, struct scatterlist *sg; unsigned int i; + if (!(buf_slot->is_dma_need_sync & (1U << lnk->link_idx))) + return; + /* for now there is just one DMA address */ for_each_sg(buf_slot->sgt[lnk->link_idx].sgl, sg, buf_slot->sgt[lnk->link_idx].nents, i) { diff --git a/net/smc/smc_ib.h b/net/smc/smc_ib.h index f90d15eae2aa..d08c58229d4c 100644 --- a/net/smc/smc_ib.h +++ b/net/smc/smc_ib.h @@ -79,6 +79,8 @@ long smc_ib_setup_per_ibdev(struct smc_ib_device *smcibdev); int smc_ib_get_memory_region(struct ib_pd *pd, int access_flags, struct smc_buf_desc *buf_slot, u8 link_idx); void smc_ib_put_memory_region(struct ib_mr *mr); +bool smc_ib_is_sg_need_sync(struct smc_link *lnk, + struct smc_buf_desc *buf_slot); void smc_ib_sync_sg_for_cpu(struct smc_link *lnk, struct smc_buf_desc *buf_slot, enum dma_data_direction data_direction); -- Gitee