Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Junxian Huang and committed by
Leon Romanovsky
b37ad2e2 cdb3a6f1

+251 -1
+3 -1
drivers/infiniband/hw/hns/Makefile
··· 4 4 # 5 5 6 6 ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3 7 + ccflags-y += -I $(srctree)/drivers/net/ethernet/hisilicon/hns3/hns3pf 8 + ccflags-y += -I $(srctree)/drivers/net/ethernet/hisilicon/hns3/hns3_common 7 9 ccflags-y += -I $(src) 8 10 9 11 hns-roce-hw-v2-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_pd.o \ 10 12 hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \ 11 13 hns_roce_cq.o hns_roce_alloc.o hns_roce_db.o hns_roce_srq.o hns_roce_restrack.o \ 12 - hns_roce_debugfs.o hns_roce_hw_v2.o 14 + hns_roce_debugfs.o hns_roce_hw_v2.o hns_roce_bond.o 13 15 14 16 obj-$(CONFIG_INFINIBAND_HNS_HIP08) += hns-roce-hw-v2.o
+192
drivers/infiniband/hw/hns/hns_roce_bond.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (c) 2025 Hisilicon Limited. 4 + */ 5 + 6 + #include "hns_roce_device.h" 7 + #include "hns_roce_hw_v2.h" 8 + #include "hns_roce_bond.h" 9 + 10 + static DEFINE_XARRAY(roce_bond_xa); 11 + 12 + static struct net_device *get_upper_dev_from_ndev(struct net_device *net_dev) 13 + { 14 + struct net_device *upper_dev; 15 + 16 + rcu_read_lock(); 17 + upper_dev = netdev_master_upper_dev_get_rcu(net_dev); 18 + dev_hold(upper_dev); 19 + rcu_read_unlock(); 20 + 21 + return upper_dev; 22 + } 23 + 24 + static int get_netdev_bond_slave_id(struct net_device *net_dev, 25 + struct hns_roce_bond_group *bond_grp) 26 + { 27 + int i; 28 + 29 + for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) 30 + if (net_dev == bond_grp->bond_func_info[i].net_dev) 31 + return i; 32 + 33 + return -ENOENT; 34 + } 35 + 36 + struct hns_roce_bond_group *hns_roce_get_bond_grp(struct net_device *net_dev, 37 + u8 bus_num) 38 + { 39 + struct hns_roce_die_info *die_info = xa_load(&roce_bond_xa, bus_num); 40 + struct hns_roce_bond_group *bond_grp; 41 + struct net_device *upper_dev = NULL; 42 + int i; 43 + 44 + if (!die_info) 45 + return NULL; 46 + 47 + for (i = 0; i < ROCE_BOND_NUM_MAX; i++) { 48 + bond_grp = die_info->bgrps[i]; 49 + if (!bond_grp) 50 + continue; 51 + if (get_netdev_bond_slave_id(net_dev, bond_grp) >= 0) 52 + return bond_grp; 53 + if (bond_grp->upper_dev) { 54 + upper_dev = get_upper_dev_from_ndev(net_dev); 55 + if (bond_grp->upper_dev == upper_dev) { 56 + dev_put(upper_dev); 57 + return bond_grp; 58 + } 59 + dev_put(upper_dev); 60 + } 61 + } 62 + 63 + return NULL; 64 + } 65 + 66 + static struct hns_roce_die_info *alloc_die_info(int bus_num) 67 + { 68 + struct hns_roce_die_info *die_info; 69 + int ret; 70 + 71 + die_info = kzalloc(sizeof(*die_info), GFP_KERNEL); 72 + if (!die_info) 73 + return NULL; 74 + 75 + ret = xa_err(xa_store(&roce_bond_xa, bus_num, die_info, GFP_KERNEL)); 76 + if (ret) { 77 + kfree(die_info); 78 + return NULL; 79 + } 80 + 81 + return die_info; 82 + } 83 + 84 + static void dealloc_die_info(struct hns_roce_die_info *die_info, u8 bus_num) 85 + { 86 + xa_erase(&roce_bond_xa, bus_num); 87 + kfree(die_info); 88 + } 89 + 90 + static int alloc_bond_id(struct hns_roce_bond_group *bond_grp) 91 + { 92 + u8 bus_num = bond_grp->bus_num; 93 + struct hns_roce_die_info *die_info = xa_load(&roce_bond_xa, bus_num); 94 + int i; 95 + 96 + if (!die_info) { 97 + die_info = alloc_die_info(bus_num); 98 + if (!die_info) 99 + return -ENOMEM; 100 + } 101 + 102 + for (i = 0; i < ROCE_BOND_NUM_MAX; i++) { 103 + if (die_info->bond_id_mask & BOND_ID(i)) 104 + continue; 105 + 106 + die_info->bond_id_mask |= BOND_ID(i); 107 + die_info->bgrps[i] = bond_grp; 108 + bond_grp->bond_id = i; 109 + 110 + return 0; 111 + } 112 + 113 + return -ENOSPC; 114 + } 115 + 116 + static int remove_bond_id(int bus_num, u8 bond_id) 117 + { 118 + struct hns_roce_die_info *die_info = xa_load(&roce_bond_xa, bus_num); 119 + 120 + if (bond_id >= ROCE_BOND_NUM_MAX) 121 + return -EINVAL; 122 + 123 + if (!die_info) 124 + return -ENODEV; 125 + 126 + die_info->bond_id_mask &= ~BOND_ID(bond_id); 127 + die_info->bgrps[bond_id] = NULL; 128 + if (!die_info->bond_id_mask) 129 + dealloc_die_info(die_info, bus_num); 130 + 131 + return 0; 132 + } 133 + 134 + int hns_roce_alloc_bond_grp(struct hns_roce_dev *hr_dev) 135 + { 136 + struct hns_roce_bond_group *bgrps[ROCE_BOND_NUM_MAX]; 137 + struct hns_roce_bond_group *bond_grp; 138 + u8 bus_num = get_hr_bus_num(hr_dev); 139 + int ret; 140 + int i; 141 + 142 + if (xa_load(&roce_bond_xa, bus_num)) 143 + return 0; 144 + 145 + for (i = 0; i < ROCE_BOND_NUM_MAX; i++) { 146 + bond_grp = kvzalloc(sizeof(*bond_grp), GFP_KERNEL); 147 + if (!bond_grp) { 148 + ret = -ENOMEM; 149 + goto mem_err; 150 + } 151 + 152 + bond_grp->bus_num = bus_num; 153 + 154 + ret = alloc_bond_id(bond_grp); 155 + if (ret) { 156 + dev_err(hr_dev->dev, 157 + "failed to alloc bond ID, ret = %d.\n", ret); 158 + goto alloc_id_err; 159 + } 160 + 161 + bgrps[i] = bond_grp; 162 + } 163 + 164 + return 0; 165 + 166 + alloc_id_err: 167 + kvfree(bond_grp); 168 + mem_err: 169 + for (i--; i >= 0; i--) { 170 + remove_bond_id(bgrps[i]->bus_num, bgrps[i]->bond_id); 171 + kvfree(bgrps[i]); 172 + } 173 + return ret; 174 + } 175 + 176 + void hns_roce_dealloc_bond_grp(void) 177 + { 178 + struct hns_roce_bond_group *bond_grp; 179 + struct hns_roce_die_info *die_info; 180 + unsigned long id; 181 + int i; 182 + 183 + xa_for_each(&roce_bond_xa, id, die_info) { 184 + for (i = 0; i < ROCE_BOND_NUM_MAX; i++) { 185 + bond_grp = die_info->bgrps[i]; 186 + if (!bond_grp) 187 + continue; 188 + remove_bond_id(bond_grp->bus_num, bond_grp->bond_id); 189 + kvfree(bond_grp); 190 + } 191 + } 192 + }
+38
drivers/infiniband/hw/hns/hns_roce_bond.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright (c) 2025 Hisilicon Limited. 4 + */ 5 + 6 + #ifndef _HNS_ROCE_BOND_H 7 + #define _HNS_ROCE_BOND_H 8 + 9 + #include <linux/netdevice.h> 10 + #include <net/bonding.h> 11 + 12 + #define ROCE_BOND_FUNC_MAX 4 13 + #define ROCE_BOND_NUM_MAX 2 14 + 15 + #define BOND_ID(id) BIT(id) 16 + 17 + struct hns_roce_func_info { 18 + struct net_device *net_dev; 19 + }; 20 + 21 + struct hns_roce_bond_group { 22 + struct net_device *upper_dev; 23 + u8 bond_id; 24 + u8 bus_num; 25 + struct hns_roce_func_info bond_func_info[ROCE_BOND_FUNC_MAX]; 26 + }; 27 + 28 + struct hns_roce_die_info { 29 + u8 bond_id_mask; 30 + struct hns_roce_bond_group *bgrps[ROCE_BOND_NUM_MAX]; 31 + }; 32 + 33 + struct hns_roce_bond_group *hns_roce_get_bond_grp(struct net_device *net_dev, 34 + u8 bus_num); 35 + int hns_roce_alloc_bond_grp(struct hns_roce_dev *hr_dev); 36 + void hns_roce_dealloc_bond_grp(void); 37 + 38 + #endif
+1
drivers/infiniband/hw/hns/hns_roce_device.h
··· 154 154 HNS_ROCE_CAP_FLAG_SDI_MODE = BIT(14), 155 155 HNS_ROCE_CAP_FLAG_STASH = BIT(17), 156 156 HNS_ROCE_CAP_FLAG_CQE_INLINE = BIT(19), 157 + HNS_ROCE_CAP_FLAG_BOND = BIT(21), 157 158 HNS_ROCE_CAP_FLAG_SRQ_RECORD_DB = BIT(22), 158 159 }; 159 160
+6
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
··· 43 43 #include <rdma/ib_umem.h> 44 44 #include <rdma/uverbs_ioctl.h> 45 45 46 + #include "hclge_main.h" 46 47 #include "hns_roce_common.h" 47 48 #include "hns_roce_device.h" 48 49 #include "hns_roce_cmd.h" 49 50 #include "hns_roce_hem.h" 50 51 #include "hns_roce_hw_v2.h" 52 + #include "hns_roce_bond.h" 51 53 52 54 #define CREATE_TRACE_POINTS 53 55 #include "hns_roce_trace.h" ··· 2271 2269 caps->flags = hr_reg_read(resp_c, PF_CAPS_C_CAP_FLAGS); 2272 2270 caps->flags |= le16_to_cpu(resp_d->cap_flags_ex) << 2273 2271 HNS_ROCE_CAP_FLAGS_EX_SHIFT; 2272 + 2273 + if (hr_dev->is_vf) 2274 + caps->flags &= ~HNS_ROCE_CAP_FLAG_BOND; 2274 2275 2275 2276 caps->num_cqs = 1 << hr_reg_read(resp_c, PF_CAPS_C_NUM_CQS); 2276 2277 caps->gid_table_len[0] = hr_reg_read(resp_c, PF_CAPS_C_MAX_GID); ··· 7265 7260 7266 7261 static void __exit hns_roce_hw_v2_exit(void) 7267 7262 { 7263 + hns_roce_dealloc_bond_grp(); 7268 7264 hnae3_unregister_client(&hns_roce_hw_v2_client); 7269 7265 hns_roce_cleanup_debugfs(); 7270 7266 }
+11
drivers/infiniband/hw/hns/hns_roce_main.c
··· 40 40 #include "hns_roce_device.h" 41 41 #include "hns_roce_hem.h" 42 42 #include "hns_roce_hw_v2.h" 43 + #include "hns_roce_bond.h" 43 44 44 45 static int hns_roce_set_mac(struct hns_roce_dev *hr_dev, u32 port, 45 46 const u8 *addr) ··· 745 744 ib_set_device_ops(ib_dev, hr_dev->hw->hns_roce_dev_ops); 746 745 ib_set_device_ops(ib_dev, &hns_roce_dev_ops); 747 746 ib_set_device_ops(ib_dev, &hns_roce_dev_restrack_ops); 747 + 748 + if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND) { 749 + ret = hns_roce_alloc_bond_grp(hr_dev); 750 + if (ret) { 751 + dev_err(dev, "failed to alloc bond_grp for bus %u, ret = %d\n", 752 + get_hr_bus_num(hr_dev), ret); 753 + return ret; 754 + } 755 + } 756 + 748 757 for (i = 0; i < hr_dev->caps.num_ports; i++) { 749 758 net_dev = get_hr_netdev(hr_dev, i); 750 759 if (!net_dev)