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

RDMA/hns: Support link state reporting for bond

The link state of bond depends on the upper device. Adapt current
link state querying flow and ib_event dispatching flow to report
correct link state of bond.

Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
Link: https://patch.msgid.link/20251112093510.3696363-8-huangjunxian6@hisilicon.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>

authored by

Junxian Huang and committed by
Leon Romanovsky
e72d274f 5d91677b

+83 -24
+8
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
··· 7358 7358 if (linkup || !hr_dev) 7359 7359 return; 7360 7360 7361 + /* For bond device, the link status depends on the upper netdev, 7362 + * and the upper device's link status depends on all the slaves' 7363 + * netdev but not only one. So bond device cannot get a correct 7364 + * link status from this path. 7365 + */ 7366 + if (hns_roce_get_bond_grp(netdev, get_hr_bus_num(hr_dev))) 7367 + return; 7368 + 7361 7369 ib_dispatch_port_state_event(&hr_dev->ib_dev, netdev); 7362 7370 } 7363 7371
+75 -24
drivers/infiniband/hw/hns/hns_roce_main.c
··· 89 89 return ret; 90 90 } 91 91 92 - static int handle_en_event(struct hns_roce_dev *hr_dev, u32 port, 93 - unsigned long event) 92 + static int hns_roce_get_port_state(struct hns_roce_dev *hr_dev, u32 port_num, 93 + enum ib_port_state *state) 94 94 { 95 + struct hns_roce_bond_group *bond_grp; 96 + u8 bus_num = get_hr_bus_num(hr_dev); 97 + struct net_device *net_dev; 98 + 99 + net_dev = ib_device_get_netdev(&hr_dev->ib_dev, port_num); 100 + if (!net_dev) 101 + return -ENODEV; 102 + 103 + if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND) { 104 + bond_grp = hns_roce_get_bond_grp(net_dev, bus_num); 105 + if (bond_grp) { 106 + *state = ib_get_curr_port_state(bond_grp->upper_dev); 107 + goto out; 108 + } 109 + } 110 + 111 + *state = ib_get_curr_port_state(net_dev); 112 + out: 113 + dev_put(net_dev); 114 + return 0; 115 + } 116 + 117 + static int handle_en_event(struct net_device *netdev, 118 + struct hns_roce_dev *hr_dev, 119 + u32 port, unsigned long event) 120 + { 121 + struct ib_device *ibdev = &hr_dev->ib_dev; 95 122 struct device *dev = hr_dev->dev; 96 - struct net_device *netdev; 123 + enum ib_port_state curr_state; 124 + struct ib_event ibevent; 97 125 int ret = 0; 98 126 99 - netdev = hr_dev->iboe.netdevs[port]; 100 127 if (!netdev) { 101 128 dev_err(dev, "can't find netdev on port(%u)!\n", port); 102 129 return -ENODEV; 103 130 } 104 131 105 132 switch (event) { 106 - case NETDEV_UP: 107 - case NETDEV_CHANGE: 108 133 case NETDEV_REGISTER: 109 134 case NETDEV_CHANGEADDR: 110 135 ret = hns_roce_set_mac(hr_dev, port, netdev->dev_addr); 111 136 break; 137 + case NETDEV_UP: 138 + case NETDEV_CHANGE: 139 + ret = hns_roce_set_mac(hr_dev, port, netdev->dev_addr); 140 + if (ret) 141 + return ret; 142 + fallthrough; 112 143 case NETDEV_DOWN: 113 - /* 114 - * In v1 engine, only support all ports closed together. 115 - */ 144 + if (!netif_is_lag_master(netdev)) 145 + break; 146 + curr_state = ib_get_curr_port_state(netdev); 147 + 148 + write_lock_irq(&ibdev->cache_lock); 149 + if (ibdev->port_data[port].cache.last_port_state == curr_state) { 150 + write_unlock_irq(&ibdev->cache_lock); 151 + return 0; 152 + } 153 + ibdev->port_data[port].cache.last_port_state = curr_state; 154 + write_unlock_irq(&ibdev->cache_lock); 155 + 156 + ibevent.event = (curr_state == IB_PORT_DOWN) ? 157 + IB_EVENT_PORT_ERR : IB_EVENT_PORT_ACTIVE; 158 + ibevent.device = ibdev; 159 + ibevent.element.port_num = port + 1; 160 + ib_dispatch_event(&ibevent); 116 161 break; 117 162 default: 118 163 dev_dbg(dev, "NETDEV event = 0x%x!\n", (u32)(event)); ··· 171 126 unsigned long event, void *ptr) 172 127 { 173 128 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 129 + struct hns_roce_bond_group *bond_grp; 174 130 struct hns_roce_ib_iboe *iboe = NULL; 175 131 struct hns_roce_dev *hr_dev = NULL; 132 + struct net_device *upper = NULL; 176 133 int ret; 177 134 u32 port; 178 135 179 136 hr_dev = container_of(self, struct hns_roce_dev, iboe.nb); 180 137 iboe = &hr_dev->iboe; 138 + if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND) { 139 + bond_grp = hns_roce_get_bond_grp(get_hr_netdev(hr_dev, 0), 140 + get_hr_bus_num(hr_dev)); 141 + upper = bond_grp ? bond_grp->upper_dev : NULL; 142 + } 181 143 182 144 for (port = 0; port < hr_dev->caps.num_ports; port++) { 183 - if (dev == iboe->netdevs[port]) { 184 - ret = handle_en_event(hr_dev, port, event); 145 + if ((!upper && dev == iboe->netdevs[port]) || 146 + (upper && dev == upper)) { 147 + ret = handle_en_event(dev, hr_dev, port, event); 185 148 if (ret) 186 149 return NOTIFY_DONE; 187 150 break; ··· 275 222 struct ib_port_attr *props) 276 223 { 277 224 struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev); 278 - struct device *dev = hr_dev->dev; 279 225 struct net_device *net_dev; 280 - unsigned long flags; 281 226 enum ib_mtu mtu; 282 227 u32 port; 283 228 int ret; ··· 296 245 if (ret) 297 246 ibdev_warn(ib_dev, "failed to get speed, ret = %d.\n", ret); 298 247 299 - spin_lock_irqsave(&hr_dev->iboe.lock, flags); 300 - 301 - net_dev = get_hr_netdev(hr_dev, port); 248 + net_dev = ib_device_get_netdev(ib_dev, port_num); 302 249 if (!net_dev) { 303 - spin_unlock_irqrestore(&hr_dev->iboe.lock, flags); 304 - dev_err(dev, "find netdev %u failed!\n", port); 250 + ibdev_err(ib_dev, "find netdev %u failed!\n", port); 305 251 return -EINVAL; 306 252 } 307 253 308 254 mtu = iboe_get_mtu(net_dev->mtu); 309 255 props->active_mtu = mtu ? min(props->max_mtu, mtu) : IB_MTU_256; 310 - props->state = netif_running(net_dev) && netif_carrier_ok(net_dev) ? 311 - IB_PORT_ACTIVE : 312 - IB_PORT_DOWN; 256 + 257 + dev_put(net_dev); 258 + 259 + ret = hns_roce_get_port_state(hr_dev, port_num, &props->state); 260 + if (ret) { 261 + ibdev_err(ib_dev, "failed to get port state.\n"); 262 + return ret; 263 + } 264 + 313 265 props->phys_state = props->state == IB_PORT_ACTIVE ? 314 266 IB_PORT_PHYS_STATE_LINK_UP : 315 267 IB_PORT_PHYS_STATE_DISABLED; 316 - 317 - spin_unlock_irqrestore(&hr_dev->iboe.lock, flags); 318 - 319 268 return 0; 320 269 } 321 270