Skip to content

Commit 21edbab

Browse files
author
Mete Durlu
committed
net/smc: Use percpu ref for wr tx reference
JIRA: https://issues.redhat.com/browse/RHEL-73484 commit 79a2223 Author: Kai Shen <[email protected]> Date: Fri Mar 17 03:21:32 2023 +0000 net/smc: Use percpu ref for wr tx reference The refcount wr_tx_refcnt may cause cache thrashing problems among cores and we can use percpu ref to mitigate this issue here. We gain some performance improvement with percpu ref here on our customized smc-r verion. Applying cache alignment may also mitigate this problem but it seem more reasonable to use percpu ref here. We can also replace wr_reg_refcnt with one percpu reference like wr_tx_refcnt. redis-benchmark on smc-r with atomic wr_tx_refcnt: SET: 525707.06 requests per second, p50=0.087 msec GET: 554877.38 requests per second, p50=0.087 msec redis-benchmark on the percpu_ref version: SET: 540482.06 requests per second, p50=0.087 msec GET: 570711.12 requests per second, p50=0.079 msec Cases are like "redis-benchmark -h x.x.x.x -q -t set,get -P 1 -n 5000000 -c 50 -d 10 --threads 4". Signed-off-by: Kai Shen <[email protected]> Reviewed-by: Tony Lu <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Mete Durlu <[email protected]>
1 parent 667bb71 commit 21edbab

File tree

3 files changed

+38
-12
lines changed

3 files changed

+38
-12
lines changed

net/smc/smc_core.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ struct smc_link {
106106
unsigned long *wr_tx_mask; /* bit mask of used indexes */
107107
u32 wr_tx_cnt; /* number of WR send buffers */
108108
wait_queue_head_t wr_tx_wait; /* wait for free WR send buf */
109-
atomic_t wr_tx_refcnt; /* tx refs to link */
109+
struct {
110+
struct percpu_ref wr_tx_refs;
111+
} ____cacheline_aligned_in_smp;
112+
struct completion tx_ref_comp;
110113

111114
struct smc_wr_buf *wr_rx_bufs; /* WR recv payload buffers */
112115
struct ib_recv_wr *wr_rx_ibs; /* WR recv meta data */
@@ -122,7 +125,10 @@ struct smc_link {
122125

123126
struct ib_reg_wr wr_reg; /* WR register memory region */
124127
wait_queue_head_t wr_reg_wait; /* wait for wr_reg result */
125-
atomic_t wr_reg_refcnt; /* reg refs to link */
128+
struct {
129+
struct percpu_ref wr_reg_refs;
130+
} ____cacheline_aligned_in_smp;
131+
struct completion reg_ref_comp;
126132
enum smc_wr_reg_state wr_reg_state; /* state of wr_reg request */
127133

128134
u8 gid[SMC_GID_SIZE];/* gid matching used vlan id*/

net/smc/smc_wr.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -377,12 +377,11 @@ int smc_wr_reg_send(struct smc_link *link, struct ib_mr *mr)
377377
if (rc)
378378
return rc;
379379

380-
atomic_inc(&link->wr_reg_refcnt);
380+
percpu_ref_get(&link->wr_reg_refs);
381381
rc = wait_event_interruptible_timeout(link->wr_reg_wait,
382382
(link->wr_reg_state != POSTED),
383383
SMC_WR_REG_MR_WAIT_TIME);
384-
if (atomic_dec_and_test(&link->wr_reg_refcnt))
385-
wake_up_all(&link->wr_reg_wait);
384+
percpu_ref_put(&link->wr_reg_refs);
386385
if (!rc) {
387386
/* timeout - terminate link */
388387
smcr_link_down_cond_sched(link);
@@ -647,8 +646,10 @@ void smc_wr_free_link(struct smc_link *lnk)
647646
smc_wr_wakeup_tx_wait(lnk);
648647

649648
smc_wr_tx_wait_no_pending_sends(lnk);
650-
wait_event(lnk->wr_reg_wait, (!atomic_read(&lnk->wr_reg_refcnt)));
651-
wait_event(lnk->wr_tx_wait, (!atomic_read(&lnk->wr_tx_refcnt)));
649+
percpu_ref_kill(&lnk->wr_reg_refs);
650+
wait_for_completion(&lnk->reg_ref_comp);
651+
percpu_ref_kill(&lnk->wr_tx_refs);
652+
wait_for_completion(&lnk->tx_ref_comp);
652653

653654
if (lnk->wr_rx_dma_addr) {
654655
ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr,
@@ -847,6 +848,20 @@ void smc_wr_add_dev(struct smc_ib_device *smcibdev)
847848
tasklet_setup(&smcibdev->send_tasklet, smc_wr_tx_tasklet_fn);
848849
}
849850

851+
static void smcr_wr_tx_refs_free(struct percpu_ref *ref)
852+
{
853+
struct smc_link *lnk = container_of(ref, struct smc_link, wr_tx_refs);
854+
855+
complete(&lnk->tx_ref_comp);
856+
}
857+
858+
static void smcr_wr_reg_refs_free(struct percpu_ref *ref)
859+
{
860+
struct smc_link *lnk = container_of(ref, struct smc_link, wr_reg_refs);
861+
862+
complete(&lnk->reg_ref_comp);
863+
}
864+
850865
int smc_wr_create_link(struct smc_link *lnk)
851866
{
852867
struct ib_device *ibdev = lnk->smcibdev->ibdev;
@@ -890,9 +905,15 @@ int smc_wr_create_link(struct smc_link *lnk)
890905
smc_wr_init_sge(lnk);
891906
bitmap_zero(lnk->wr_tx_mask, SMC_WR_BUF_CNT);
892907
init_waitqueue_head(&lnk->wr_tx_wait);
893-
atomic_set(&lnk->wr_tx_refcnt, 0);
908+
rc = percpu_ref_init(&lnk->wr_tx_refs, smcr_wr_tx_refs_free, 0, GFP_KERNEL);
909+
if (rc)
910+
goto dma_unmap;
911+
init_completion(&lnk->tx_ref_comp);
894912
init_waitqueue_head(&lnk->wr_reg_wait);
895-
atomic_set(&lnk->wr_reg_refcnt, 0);
913+
rc = percpu_ref_init(&lnk->wr_reg_refs, smcr_wr_reg_refs_free, 0, GFP_KERNEL);
914+
if (rc)
915+
goto dma_unmap;
916+
init_completion(&lnk->reg_ref_comp);
896917
init_waitqueue_head(&lnk->wr_rx_empty_wait);
897918
return rc;
898919

net/smc/smc_wr.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,13 @@ static inline bool smc_wr_tx_link_hold(struct smc_link *link)
6363
{
6464
if (!smc_link_sendable(link))
6565
return false;
66-
atomic_inc(&link->wr_tx_refcnt);
66+
percpu_ref_get(&link->wr_tx_refs);
6767
return true;
6868
}
6969

7070
static inline void smc_wr_tx_link_put(struct smc_link *link)
7171
{
72-
if (atomic_dec_and_test(&link->wr_tx_refcnt))
73-
wake_up_all(&link->wr_tx_wait);
72+
percpu_ref_put(&link->wr_tx_refs);
7473
}
7574

7675
static inline void smc_wr_drain_cq(struct smc_link *lnk)

0 commit comments

Comments
 (0)