Commit 49f27d3e authored by Junxian Huang's avatar Junxian Huang Committed by ZhouJuan
Browse files

RDMA/hns: Support dispatching IB event for RoCE bonding

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I6ZAIM



---------------------------------------------------------------

Support dispatching IB event for RoCE bonding. After setting bond,
IB_EVENT_PORT_ERR is dispatched in the following situation:
	1. bond0 becomes link down;
	2. all slaves become link down (as it will lead to a link-down
           of the upper device).

IB_EVENT_PORT_ACTIVE is dispatched in the following situation:
	1. bond0 becomes link up;
	2. one slave becomes link up when all slaves were link down (as
           it will lead to a link-up of the upper device).

Signed-off-by: default avatarJunxian Huang <huangjunxian6@hisilicon.com>
parent c65db67a
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -136,16 +136,17 @@ struct net_device *hns_roce_get_bond_netdev(struct hns_roce_dev *hr_dev)
	if (bond_grp->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
		for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) {
			net_dev = bond_grp->bond_func_info[i].net_dev;
			if (net_dev && is_active_slave(net_dev, bond_grp))
				break;
			if (net_dev && is_active_slave(net_dev, bond_grp) &&
			    get_port_state(net_dev) == IB_PORT_ACTIVE)
				goto out;
		}
	} else {
	}

	for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) {
		net_dev = bond_grp->bond_func_info[i].net_dev;
		if (net_dev && get_port_state(net_dev) == IB_PORT_ACTIVE)
			break;
	}
	}

out:
	mutex_unlock(&bond_grp->bond_mutex);
+10 −0
Original line number Diff line number Diff line
@@ -7570,6 +7570,7 @@ static void hns_roce_hw_v2_link_status_change(struct hnae3_handle *handle,
{
	struct net_device *netdev = handle->rinfo.netdev;
	struct hns_roce_dev *hr_dev = handle->priv;
	struct hns_roce_bond_group *bond_grp;
	struct ib_event event;
	unsigned long flags;
	u8 phy_port;
@@ -7577,6 +7578,15 @@ static void hns_roce_hw_v2_link_status_change(struct hnae3_handle *handle,
	if (linkup || !hr_dev)
		return;

	/* For bond device, the link status depends on the upper netdev,
	 * and the upper device's link status depends on all the slaves'
	 * netdev but not only one. So bond device cannot get a correct
	 * link status from this path.
	 */
	bond_grp = hns_roce_get_bond_grp(hr_dev);
	if (bond_grp)
		return;

	for (phy_port = 0; phy_port < hr_dev->caps.num_ports; phy_port++)
		if (netdev == hr_dev->iboe.netdevs[phy_port])
			break;
+12 −6
Original line number Diff line number Diff line
@@ -131,17 +131,16 @@ static enum ib_port_state get_upper_port_state(struct hns_roce_dev *hr_dev)
	return IB_PORT_ACTIVE;
}

static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port,
			   unsigned long dev_event)
static int handle_en_event(struct net_device *netdev,
			   struct hns_roce_dev *hr_dev,
			   u32 port, unsigned long dev_event)
{
	struct device *dev = hr_dev->dev;
	enum ib_port_state port_state;
	struct net_device *netdev;
	struct ib_event event;
	unsigned long flags;
	int ret = 0;

	netdev = hr_dev->iboe.netdevs[port];
	if (!netdev) {
		dev_err(dev, "Can't find netdev on port(%u)!\n", port);
		return -ENODEV;
@@ -189,17 +188,24 @@ static int hns_roce_netdev_event(struct notifier_block *self,
				 unsigned long event, void *ptr)
{
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
	struct hns_roce_bond_group *bond_grp;
	struct hns_roce_ib_iboe *iboe = NULL;
	struct hns_roce_dev *hr_dev = NULL;
	struct net_device *upper = NULL;
	int ret;
	u8 port;

	hr_dev = container_of(self, struct hns_roce_dev, iboe.nb);
	iboe = &hr_dev->iboe;
	if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND) {
		bond_grp = hns_roce_get_bond_grp(hr_dev);
		upper = bond_grp ? bond_grp->upper_dev : NULL;
	}

	for (port = 0; port < hr_dev->caps.num_ports; port++) {
		if (dev == iboe->netdevs[port]) {
			ret = handle_en_event(hr_dev, port, event);
		if ((!upper && dev == iboe->netdevs[port]) ||
		    (upper && dev == upper)) {
			ret = handle_en_event(dev, hr_dev, port, event);
			if (ret)
				return NOTIFY_DONE;
			break;