drivers/infiniband/hw/hns/hns_roce_bond.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/hns/hns_roce_bond.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/hns/hns_roce_bond.c
Extension
.c
Size
25128 bytes
Lines
1013
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

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 int hns_roce_set_bond_netdev(struct hns_roce_bond_group *bond_grp,
				    struct hns_roce_dev *hr_dev)
{
	struct net_device *active_dev;
	struct net_device *old_dev;
	int i, ret = 0;

	if (bond_grp->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
		rcu_read_lock();
		active_dev =
			bond_option_active_slave_get_rcu(netdev_priv(bond_grp->upper_dev));
		rcu_read_unlock();
	} else {
		for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) {
			active_dev = bond_grp->bond_func_info[i].net_dev;
			if (active_dev &&
			    ib_get_curr_port_state(active_dev) == IB_PORT_ACTIVE)
				break;
		}
	}

	if (!active_dev || i == ROCE_BOND_FUNC_MAX)
		active_dev = get_hr_netdev(hr_dev, 0);

	old_dev = ib_device_get_netdev(&hr_dev->ib_dev, 1);
	if (old_dev == active_dev)
		goto out;

	ret = ib_device_set_netdev(&hr_dev->ib_dev, active_dev, 1);
	if (ret) {
		dev_err(hr_dev->dev, "failed to set netdev for bond.\n");
		goto out;
	}

	if (bond_grp->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
		if (old_dev)
			roce_del_all_netdev_gids(&hr_dev->ib_dev, 1, old_dev);
		rdma_roce_rescan_port(&hr_dev->ib_dev, 1);
	}
out:
	dev_put(old_dev);
	return ret;
}

bool hns_roce_bond_is_active(struct hns_roce_dev *hr_dev)
{
	struct net_device *net_dev = get_hr_netdev(hr_dev, 0);
	struct hns_roce_bond_group *bond_grp;
	u8 bus_num = get_hr_bus_num(hr_dev);

	bond_grp = hns_roce_get_bond_grp(net_dev, bus_num);
	if (bond_grp && bond_grp->bond_state != HNS_ROCE_BOND_NOT_BONDED &&
	    bond_grp->bond_state != HNS_ROCE_BOND_NOT_ATTACHED)
		return true;

	return false;
}

static void hns_roce_bond_get_active_slave(struct hns_roce_bond_group *bond_grp)
{
	struct net_device *net_dev;
	u32 active_slave_map = 0;
	u8 active_slave_num = 0;
	bool active;
	u8 i;

	for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) {
		net_dev = bond_grp->bond_func_info[i].net_dev;
		if (!net_dev || !(bond_grp->slave_map & (1U << i)))
			continue;

		active = (bond_grp->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) ?
			 net_lag_port_dev_txable(net_dev) :
			 (ib_get_curr_port_state(net_dev) == IB_PORT_ACTIVE);
		if (active) {
			active_slave_num++;
			active_slave_map |= (1U << i);

Annotation

Implementation Notes