Skip to content

Commit faa6244

Browse files
Feng Fangrleon
authored andcommitted
RDMA/hns: Fix different dgids mapping to the same dip_idx
DIP algorithm requires a one-to-one mapping between dgid and dip_idx. Currently a queue 'spare_idx' is used to store QPN of QPs that use DIP algorithm. For a new dgid, use a QPN from spare_idx as dip_idx. This method lacks a mechanism for deduplicating QPN, which may result in different dgids sharing the same dip_idx and break the one-to-one mapping requirement. This patch replaces spare_idx with xarray and introduces a refcnt of a dip_idx to indicate the number of QPs that using this dip_idx. The state machine for dip_idx management is implemented as: * The entry at an index in xarray is empty -- This indicates that the corresponding dip_idx hasn't been created. * The entry at an index in xarray is not empty but with 0 refcnt -- This indicates that the corresponding dip_idx has been created but not used as dip_idx yet. * The entry at an index in xarray is not empty and with non-0 refcnt -- This indicates that the corresponding dip_idx is being used by refcnt number of DIP QPs. Fixes: eb653ed ("RDMA/hns: Bugfix for incorrect association between dip_idx and dgid") Fixes: f91696f ("RDMA/hns: Support congestion control type selection according to the FW") Signed-off-by: Feng Fang <[email protected]> Signed-off-by: Junxian Huang <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Leon Romanovsky <[email protected]>
1 parent cdb21c1 commit faa6244

File tree

5 files changed

+75
-44
lines changed

5 files changed

+75
-44
lines changed

drivers/infiniband/hw/hns/hns_roce_device.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -489,12 +489,6 @@ struct hns_roce_bank {
489489
u32 next; /* Next ID to allocate. */
490490
};
491491

492-
struct hns_roce_idx_table {
493-
u32 *spare_idx;
494-
u32 head;
495-
u32 tail;
496-
};
497-
498492
struct hns_roce_qp_table {
499493
struct hns_roce_hem_table qp_table;
500494
struct hns_roce_hem_table irrl_table;
@@ -503,7 +497,7 @@ struct hns_roce_qp_table {
503497
struct mutex scc_mutex;
504498
struct hns_roce_bank bank[HNS_ROCE_QP_BANK_NUM];
505499
struct mutex bank_mutex;
506-
struct hns_roce_idx_table idx_table;
500+
struct xarray dip_xa;
507501
};
508502

509503
struct hns_roce_cq_table {
@@ -658,6 +652,7 @@ struct hns_roce_qp {
658652
u8 tc_mode;
659653
u8 priority;
660654
spinlock_t flush_lock;
655+
struct hns_roce_dip *dip;
661656
};
662657

663658
struct hns_roce_ib_iboe {
@@ -984,8 +979,6 @@ struct hns_roce_dev {
984979
enum hns_roce_device_state state;
985980
struct list_head qp_list; /* list of all qps on this dev */
986981
spinlock_t qp_list_lock; /* protect qp_list */
987-
struct list_head dip_list; /* list of all dest ips on this dev */
988-
spinlock_t dip_list_lock; /* protect dip_list */
989982

990983
struct list_head pgdir_list;
991984
struct mutex pgdir_mutex;

drivers/infiniband/hw/hns/hns_roce_hw_v2.c

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2553,20 +2553,19 @@ static void hns_roce_free_link_table(struct hns_roce_dev *hr_dev)
25532553
free_link_table_buf(hr_dev, &priv->ext_llm);
25542554
}
25552555

2556-
static void free_dip_list(struct hns_roce_dev *hr_dev)
2556+
static void free_dip_entry(struct hns_roce_dev *hr_dev)
25572557
{
25582558
struct hns_roce_dip *hr_dip;
2559-
struct hns_roce_dip *tmp;
2560-
unsigned long flags;
2559+
unsigned long idx;
25612560

2562-
spin_lock_irqsave(&hr_dev->dip_list_lock, flags);
2561+
xa_lock(&hr_dev->qp_table.dip_xa);
25632562

2564-
list_for_each_entry_safe(hr_dip, tmp, &hr_dev->dip_list, node) {
2565-
list_del(&hr_dip->node);
2563+
xa_for_each(&hr_dev->qp_table.dip_xa, idx, hr_dip) {
2564+
__xa_erase(&hr_dev->qp_table.dip_xa, hr_dip->dip_idx);
25662565
kfree(hr_dip);
25672566
}
25682567

2569-
spin_unlock_irqrestore(&hr_dev->dip_list_lock, flags);
2568+
xa_unlock(&hr_dev->qp_table.dip_xa);
25702569
}
25712570

25722571
static struct ib_pd *free_mr_init_pd(struct hns_roce_dev *hr_dev)
@@ -2974,7 +2973,7 @@ static void hns_roce_v2_exit(struct hns_roce_dev *hr_dev)
29742973
hns_roce_free_link_table(hr_dev);
29752974

29762975
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP09)
2977-
free_dip_list(hr_dev);
2976+
free_dip_entry(hr_dev);
29782977
}
29792978

29802979
static int hns_roce_mbox_post(struct hns_roce_dev *hr_dev,
@@ -4694,46 +4693,74 @@ static int modify_qp_rtr_to_rts(struct ib_qp *ibqp, int attr_mask,
46944693
return 0;
46954694
}
46964695

4696+
static int alloc_dip_entry(struct xarray *dip_xa, u32 qpn)
4697+
{
4698+
struct hns_roce_dip *hr_dip;
4699+
int ret;
4700+
4701+
hr_dip = xa_load(dip_xa, qpn);
4702+
if (hr_dip)
4703+
return 0;
4704+
4705+
hr_dip = kzalloc(sizeof(*hr_dip), GFP_KERNEL);
4706+
if (!hr_dip)
4707+
return -ENOMEM;
4708+
4709+
ret = xa_err(xa_store(dip_xa, qpn, hr_dip, GFP_KERNEL));
4710+
if (ret)
4711+
kfree(hr_dip);
4712+
4713+
return ret;
4714+
}
4715+
46974716
static int get_dip_ctx_idx(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
46984717
u32 *dip_idx)
46994718
{
47004719
const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr);
47014720
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
4702-
u32 *spare_idx = hr_dev->qp_table.idx_table.spare_idx;
4703-
u32 *head = &hr_dev->qp_table.idx_table.head;
4704-
u32 *tail = &hr_dev->qp_table.idx_table.tail;
4721+
struct xarray *dip_xa = &hr_dev->qp_table.dip_xa;
4722+
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
47054723
struct hns_roce_dip *hr_dip;
4706-
unsigned long flags;
4724+
unsigned long idx;
47074725
int ret = 0;
47084726

4709-
spin_lock_irqsave(&hr_dev->dip_list_lock, flags);
4727+
ret = alloc_dip_entry(dip_xa, ibqp->qp_num);
4728+
if (ret)
4729+
return ret;
47104730

4711-
spare_idx[*tail] = ibqp->qp_num;
4712-
*tail = (*tail == hr_dev->caps.num_qps - 1) ? 0 : (*tail + 1);
4731+
xa_lock(dip_xa);
47134732

4714-
list_for_each_entry(hr_dip, &hr_dev->dip_list, node) {
4715-
if (!memcmp(grh->dgid.raw, hr_dip->dgid, GID_LEN_V2)) {
4733+
xa_for_each(dip_xa, idx, hr_dip) {
4734+
if (hr_dip->qp_cnt &&
4735+
!memcmp(grh->dgid.raw, hr_dip->dgid, GID_LEN_V2)) {
47164736
*dip_idx = hr_dip->dip_idx;
4737+
hr_dip->qp_cnt++;
4738+
hr_qp->dip = hr_dip;
47174739
goto out;
47184740
}
47194741
}
47204742

47214743
/* If no dgid is found, a new dip and a mapping between dgid and
47224744
* dip_idx will be created.
47234745
*/
4724-
hr_dip = kzalloc(sizeof(*hr_dip), GFP_ATOMIC);
4725-
if (!hr_dip) {
4726-
ret = -ENOMEM;
4727-
goto out;
4746+
xa_for_each(dip_xa, idx, hr_dip) {
4747+
if (hr_dip->qp_cnt)
4748+
continue;
4749+
4750+
*dip_idx = idx;
4751+
memcpy(hr_dip->dgid, grh->dgid.raw, sizeof(grh->dgid.raw));
4752+
hr_dip->dip_idx = idx;
4753+
hr_dip->qp_cnt++;
4754+
hr_qp->dip = hr_dip;
4755+
break;
47284756
}
47294757

4730-
memcpy(hr_dip->dgid, grh->dgid.raw, sizeof(grh->dgid.raw));
4731-
hr_dip->dip_idx = *dip_idx = spare_idx[*head];
4732-
*head = (*head == hr_dev->caps.num_qps - 1) ? 0 : (*head + 1);
4733-
list_add_tail(&hr_dip->node, &hr_dev->dip_list);
4758+
/* This should never happen. */
4759+
if (WARN_ON_ONCE(!hr_qp->dip))
4760+
ret = -ENOSPC;
47344761

47354762
out:
4736-
spin_unlock_irqrestore(&hr_dev->dip_list_lock, flags);
4763+
xa_unlock(dip_xa);
47374764
return ret;
47384765
}
47394766

@@ -5587,6 +5614,20 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev,
55875614
return ret;
55885615
}
55895616

5617+
static void put_dip_ctx_idx(struct hns_roce_dev *hr_dev,
5618+
struct hns_roce_qp *hr_qp)
5619+
{
5620+
struct hns_roce_dip *hr_dip = hr_qp->dip;
5621+
5622+
xa_lock(&hr_dev->qp_table.dip_xa);
5623+
5624+
hr_dip->qp_cnt--;
5625+
if (!hr_dip->qp_cnt)
5626+
memset(hr_dip->dgid, 0, GID_LEN_V2);
5627+
5628+
xa_unlock(&hr_dev->qp_table.dip_xa);
5629+
}
5630+
55905631
int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
55915632
{
55925633
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
@@ -5600,6 +5641,9 @@ int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
56005641
spin_unlock_irqrestore(&hr_qp->flush_lock, flags);
56015642
flush_work(&hr_qp->flush_work.work);
56025643

5644+
if (hr_qp->cong_type == CONG_TYPE_DIP)
5645+
put_dip_ctx_idx(hr_dev, hr_qp);
5646+
56035647
ret = hns_roce_v2_destroy_qp_common(hr_dev, hr_qp, udata);
56045648
if (ret)
56055649
ibdev_err_ratelimited(&hr_dev->ib_dev,

drivers/infiniband/hw/hns/hns_roce_hw_v2.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1348,7 +1348,7 @@ struct hns_roce_v2_priv {
13481348
struct hns_roce_dip {
13491349
u8 dgid[GID_LEN_V2];
13501350
u32 dip_idx;
1351-
struct list_head node; /* all dips are on a list */
1351+
u32 qp_cnt;
13521352
};
13531353

13541354
struct fmea_ram_ecc {

drivers/infiniband/hw/hns/hns_roce_main.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,8 +1135,6 @@ int hns_roce_init(struct hns_roce_dev *hr_dev)
11351135

11361136
INIT_LIST_HEAD(&hr_dev->qp_list);
11371137
spin_lock_init(&hr_dev->qp_list_lock);
1138-
INIT_LIST_HEAD(&hr_dev->dip_list);
1139-
spin_lock_init(&hr_dev->dip_list_lock);
11401138

11411139
ret = hns_roce_register_device(hr_dev);
11421140
if (ret)

drivers/infiniband/hw/hns/hns_roce_qp.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,14 +1573,10 @@ int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev)
15731573
unsigned int reserved_from_bot;
15741574
unsigned int i;
15751575

1576-
qp_table->idx_table.spare_idx = kcalloc(hr_dev->caps.num_qps,
1577-
sizeof(u32), GFP_KERNEL);
1578-
if (!qp_table->idx_table.spare_idx)
1579-
return -ENOMEM;
1580-
15811576
mutex_init(&qp_table->scc_mutex);
15821577
mutex_init(&qp_table->bank_mutex);
15831578
xa_init(&hr_dev->qp_table_xa);
1579+
xa_init(&qp_table->dip_xa);
15841580

15851581
reserved_from_bot = hr_dev->caps.reserved_qps;
15861582

@@ -1605,7 +1601,7 @@ void hns_roce_cleanup_qp_table(struct hns_roce_dev *hr_dev)
16051601

16061602
for (i = 0; i < HNS_ROCE_QP_BANK_NUM; i++)
16071603
ida_destroy(&hr_dev->qp_table.bank[i].ida);
1604+
xa_destroy(&hr_dev->qp_table.dip_xa);
16081605
mutex_destroy(&hr_dev->qp_table.bank_mutex);
16091606
mutex_destroy(&hr_dev->qp_table.scc_mutex);
1610-
kfree(hr_dev->qp_table.idx_table.spare_idx);
16111607
}

0 commit comments

Comments
 (0)