mirror of https://github.com/torvalds/linux.git
RDMA/hns: Initialize bonding resources
Allocate bond_grp resources for each card when the first device in this card is registered. Block the initialization of VF when its PF is a bonded slave, as VF is not supported in this case due to HW constraints. Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> Link: https://patch.msgid.link/20251112093510.3696363-3-huangjunxian6@hisilicon.com Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
cdb3a6f183
commit
b37ad2e290
|
|
@ -4,11 +4,13 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3
|
ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3
|
||||||
|
ccflags-y += -I $(srctree)/drivers/net/ethernet/hisilicon/hns3/hns3pf
|
||||||
|
ccflags-y += -I $(srctree)/drivers/net/ethernet/hisilicon/hns3/hns3_common
|
||||||
ccflags-y += -I $(src)
|
ccflags-y += -I $(src)
|
||||||
|
|
||||||
hns-roce-hw-v2-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_pd.o \
|
hns-roce-hw-v2-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_pd.o \
|
||||||
hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \
|
hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \
|
||||||
hns_roce_cq.o hns_roce_alloc.o hns_roce_db.o hns_roce_srq.o hns_roce_restrack.o \
|
hns_roce_cq.o hns_roce_alloc.o hns_roce_db.o hns_roce_srq.o hns_roce_restrack.o \
|
||||||
hns_roce_debugfs.o hns_roce_hw_v2.o
|
hns_roce_debugfs.o hns_roce_hw_v2.o hns_roce_bond.o
|
||||||
|
|
||||||
obj-$(CONFIG_INFINIBAND_HNS_HIP08) += hns-roce-hw-v2.o
|
obj-$(CONFIG_INFINIBAND_HNS_HIP08) += hns-roce-hw-v2.o
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,192 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Hisilicon Limited.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hns_roce_device.h"
|
||||||
|
#include "hns_roce_hw_v2.h"
|
||||||
|
#include "hns_roce_bond.h"
|
||||||
|
|
||||||
|
static DEFINE_XARRAY(roce_bond_xa);
|
||||||
|
|
||||||
|
static struct net_device *get_upper_dev_from_ndev(struct net_device *net_dev)
|
||||||
|
{
|
||||||
|
struct net_device *upper_dev;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
upper_dev = netdev_master_upper_dev_get_rcu(net_dev);
|
||||||
|
dev_hold(upper_dev);
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return upper_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_netdev_bond_slave_id(struct net_device *net_dev,
|
||||||
|
struct hns_roce_bond_group *bond_grp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ROCE_BOND_FUNC_MAX; i++)
|
||||||
|
if (net_dev == bond_grp->bond_func_info[i].net_dev)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hns_roce_bond_group *hns_roce_get_bond_grp(struct net_device *net_dev,
|
||||||
|
u8 bus_num)
|
||||||
|
{
|
||||||
|
struct hns_roce_die_info *die_info = xa_load(&roce_bond_xa, bus_num);
|
||||||
|
struct hns_roce_bond_group *bond_grp;
|
||||||
|
struct net_device *upper_dev = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!die_info)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < ROCE_BOND_NUM_MAX; i++) {
|
||||||
|
bond_grp = die_info->bgrps[i];
|
||||||
|
if (!bond_grp)
|
||||||
|
continue;
|
||||||
|
if (get_netdev_bond_slave_id(net_dev, bond_grp) >= 0)
|
||||||
|
return bond_grp;
|
||||||
|
if (bond_grp->upper_dev) {
|
||||||
|
upper_dev = get_upper_dev_from_ndev(net_dev);
|
||||||
|
if (bond_grp->upper_dev == upper_dev) {
|
||||||
|
dev_put(upper_dev);
|
||||||
|
return bond_grp;
|
||||||
|
}
|
||||||
|
dev_put(upper_dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct hns_roce_die_info *alloc_die_info(int bus_num)
|
||||||
|
{
|
||||||
|
struct hns_roce_die_info *die_info;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
die_info = kzalloc(sizeof(*die_info), GFP_KERNEL);
|
||||||
|
if (!die_info)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = xa_err(xa_store(&roce_bond_xa, bus_num, die_info, GFP_KERNEL));
|
||||||
|
if (ret) {
|
||||||
|
kfree(die_info);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return die_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dealloc_die_info(struct hns_roce_die_info *die_info, u8 bus_num)
|
||||||
|
{
|
||||||
|
xa_erase(&roce_bond_xa, bus_num);
|
||||||
|
kfree(die_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int alloc_bond_id(struct hns_roce_bond_group *bond_grp)
|
||||||
|
{
|
||||||
|
u8 bus_num = bond_grp->bus_num;
|
||||||
|
struct hns_roce_die_info *die_info = xa_load(&roce_bond_xa, bus_num);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!die_info) {
|
||||||
|
die_info = alloc_die_info(bus_num);
|
||||||
|
if (!die_info)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ROCE_BOND_NUM_MAX; i++) {
|
||||||
|
if (die_info->bond_id_mask & BOND_ID(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
die_info->bond_id_mask |= BOND_ID(i);
|
||||||
|
die_info->bgrps[i] = bond_grp;
|
||||||
|
bond_grp->bond_id = i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_bond_id(int bus_num, u8 bond_id)
|
||||||
|
{
|
||||||
|
struct hns_roce_die_info *die_info = xa_load(&roce_bond_xa, bus_num);
|
||||||
|
|
||||||
|
if (bond_id >= ROCE_BOND_NUM_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!die_info)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
die_info->bond_id_mask &= ~BOND_ID(bond_id);
|
||||||
|
die_info->bgrps[bond_id] = NULL;
|
||||||
|
if (!die_info->bond_id_mask)
|
||||||
|
dealloc_die_info(die_info, bus_num);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hns_roce_alloc_bond_grp(struct hns_roce_dev *hr_dev)
|
||||||
|
{
|
||||||
|
struct hns_roce_bond_group *bgrps[ROCE_BOND_NUM_MAX];
|
||||||
|
struct hns_roce_bond_group *bond_grp;
|
||||||
|
u8 bus_num = get_hr_bus_num(hr_dev);
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (xa_load(&roce_bond_xa, bus_num))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ROCE_BOND_NUM_MAX; i++) {
|
||||||
|
bond_grp = kvzalloc(sizeof(*bond_grp), GFP_KERNEL);
|
||||||
|
if (!bond_grp) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto mem_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bond_grp->bus_num = bus_num;
|
||||||
|
|
||||||
|
ret = alloc_bond_id(bond_grp);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(hr_dev->dev,
|
||||||
|
"failed to alloc bond ID, ret = %d.\n", ret);
|
||||||
|
goto alloc_id_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bgrps[i] = bond_grp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
alloc_id_err:
|
||||||
|
kvfree(bond_grp);
|
||||||
|
mem_err:
|
||||||
|
for (i--; i >= 0; i--) {
|
||||||
|
remove_bond_id(bgrps[i]->bus_num, bgrps[i]->bond_id);
|
||||||
|
kvfree(bgrps[i]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hns_roce_dealloc_bond_grp(void)
|
||||||
|
{
|
||||||
|
struct hns_roce_bond_group *bond_grp;
|
||||||
|
struct hns_roce_die_info *die_info;
|
||||||
|
unsigned long id;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
xa_for_each(&roce_bond_xa, id, die_info) {
|
||||||
|
for (i = 0; i < ROCE_BOND_NUM_MAX; i++) {
|
||||||
|
bond_grp = die_info->bgrps[i];
|
||||||
|
if (!bond_grp)
|
||||||
|
continue;
|
||||||
|
remove_bond_id(bond_grp->bus_num, bond_grp->bond_id);
|
||||||
|
kvfree(bond_grp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Hisilicon Limited.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HNS_ROCE_BOND_H
|
||||||
|
#define _HNS_ROCE_BOND_H
|
||||||
|
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <net/bonding.h>
|
||||||
|
|
||||||
|
#define ROCE_BOND_FUNC_MAX 4
|
||||||
|
#define ROCE_BOND_NUM_MAX 2
|
||||||
|
|
||||||
|
#define BOND_ID(id) BIT(id)
|
||||||
|
|
||||||
|
struct hns_roce_func_info {
|
||||||
|
struct net_device *net_dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hns_roce_bond_group {
|
||||||
|
struct net_device *upper_dev;
|
||||||
|
u8 bond_id;
|
||||||
|
u8 bus_num;
|
||||||
|
struct hns_roce_func_info bond_func_info[ROCE_BOND_FUNC_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hns_roce_die_info {
|
||||||
|
u8 bond_id_mask;
|
||||||
|
struct hns_roce_bond_group *bgrps[ROCE_BOND_NUM_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hns_roce_bond_group *hns_roce_get_bond_grp(struct net_device *net_dev,
|
||||||
|
u8 bus_num);
|
||||||
|
int hns_roce_alloc_bond_grp(struct hns_roce_dev *hr_dev);
|
||||||
|
void hns_roce_dealloc_bond_grp(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -154,6 +154,7 @@ enum {
|
||||||
HNS_ROCE_CAP_FLAG_SDI_MODE = BIT(14),
|
HNS_ROCE_CAP_FLAG_SDI_MODE = BIT(14),
|
||||||
HNS_ROCE_CAP_FLAG_STASH = BIT(17),
|
HNS_ROCE_CAP_FLAG_STASH = BIT(17),
|
||||||
HNS_ROCE_CAP_FLAG_CQE_INLINE = BIT(19),
|
HNS_ROCE_CAP_FLAG_CQE_INLINE = BIT(19),
|
||||||
|
HNS_ROCE_CAP_FLAG_BOND = BIT(21),
|
||||||
HNS_ROCE_CAP_FLAG_SRQ_RECORD_DB = BIT(22),
|
HNS_ROCE_CAP_FLAG_SRQ_RECORD_DB = BIT(22),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,13 @@
|
||||||
#include <rdma/ib_umem.h>
|
#include <rdma/ib_umem.h>
|
||||||
#include <rdma/uverbs_ioctl.h>
|
#include <rdma/uverbs_ioctl.h>
|
||||||
|
|
||||||
|
#include "hclge_main.h"
|
||||||
#include "hns_roce_common.h"
|
#include "hns_roce_common.h"
|
||||||
#include "hns_roce_device.h"
|
#include "hns_roce_device.h"
|
||||||
#include "hns_roce_cmd.h"
|
#include "hns_roce_cmd.h"
|
||||||
#include "hns_roce_hem.h"
|
#include "hns_roce_hem.h"
|
||||||
#include "hns_roce_hw_v2.h"
|
#include "hns_roce_hw_v2.h"
|
||||||
|
#include "hns_roce_bond.h"
|
||||||
|
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include "hns_roce_trace.h"
|
#include "hns_roce_trace.h"
|
||||||
|
|
@ -2270,6 +2272,9 @@ static int hns_roce_query_caps(struct hns_roce_dev *hr_dev)
|
||||||
caps->flags |= le16_to_cpu(resp_d->cap_flags_ex) <<
|
caps->flags |= le16_to_cpu(resp_d->cap_flags_ex) <<
|
||||||
HNS_ROCE_CAP_FLAGS_EX_SHIFT;
|
HNS_ROCE_CAP_FLAGS_EX_SHIFT;
|
||||||
|
|
||||||
|
if (hr_dev->is_vf)
|
||||||
|
caps->flags &= ~HNS_ROCE_CAP_FLAG_BOND;
|
||||||
|
|
||||||
caps->num_cqs = 1 << hr_reg_read(resp_c, PF_CAPS_C_NUM_CQS);
|
caps->num_cqs = 1 << hr_reg_read(resp_c, PF_CAPS_C_NUM_CQS);
|
||||||
caps->gid_table_len[0] = hr_reg_read(resp_c, PF_CAPS_C_MAX_GID);
|
caps->gid_table_len[0] = hr_reg_read(resp_c, PF_CAPS_C_MAX_GID);
|
||||||
caps->max_cqes = 1 << hr_reg_read(resp_c, PF_CAPS_C_CQ_DEPTH);
|
caps->max_cqes = 1 << hr_reg_read(resp_c, PF_CAPS_C_CQ_DEPTH);
|
||||||
|
|
@ -7260,6 +7265,7 @@ static int __init hns_roce_hw_v2_init(void)
|
||||||
|
|
||||||
static void __exit hns_roce_hw_v2_exit(void)
|
static void __exit hns_roce_hw_v2_exit(void)
|
||||||
{
|
{
|
||||||
|
hns_roce_dealloc_bond_grp();
|
||||||
hnae3_unregister_client(&hns_roce_hw_v2_client);
|
hnae3_unregister_client(&hns_roce_hw_v2_client);
|
||||||
hns_roce_cleanup_debugfs();
|
hns_roce_cleanup_debugfs();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include "hns_roce_device.h"
|
#include "hns_roce_device.h"
|
||||||
#include "hns_roce_hem.h"
|
#include "hns_roce_hem.h"
|
||||||
#include "hns_roce_hw_v2.h"
|
#include "hns_roce_hw_v2.h"
|
||||||
|
#include "hns_roce_bond.h"
|
||||||
|
|
||||||
static int hns_roce_set_mac(struct hns_roce_dev *hr_dev, u32 port,
|
static int hns_roce_set_mac(struct hns_roce_dev *hr_dev, u32 port,
|
||||||
const u8 *addr)
|
const u8 *addr)
|
||||||
|
|
@ -744,6 +745,16 @@ static int hns_roce_register_device(struct hns_roce_dev *hr_dev)
|
||||||
ib_set_device_ops(ib_dev, hr_dev->hw->hns_roce_dev_ops);
|
ib_set_device_ops(ib_dev, hr_dev->hw->hns_roce_dev_ops);
|
||||||
ib_set_device_ops(ib_dev, &hns_roce_dev_ops);
|
ib_set_device_ops(ib_dev, &hns_roce_dev_ops);
|
||||||
ib_set_device_ops(ib_dev, &hns_roce_dev_restrack_ops);
|
ib_set_device_ops(ib_dev, &hns_roce_dev_restrack_ops);
|
||||||
|
|
||||||
|
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND) {
|
||||||
|
ret = hns_roce_alloc_bond_grp(hr_dev);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to alloc bond_grp for bus %u, ret = %d\n",
|
||||||
|
get_hr_bus_num(hr_dev), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < hr_dev->caps.num_ports; i++) {
|
for (i = 0; i < hr_dev->caps.num_ports; i++) {
|
||||||
net_dev = get_hr_netdev(hr_dev, i);
|
net_dev = get_hr_netdev(hr_dev, i);
|
||||||
if (!net_dev)
|
if (!net_dev)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue