drivers/infiniband/hw/hns/hns_roce_main.c

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

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/hns/hns_roce_main.c
Extension
.c
Size
35088 bytes
Lines
1298
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) {
			*state = ib_get_curr_port_state(bond_grp->upper_dev);
			goto out;
		}
	}

	*state = ib_get_curr_port_state(net_dev);
out:
	dev_put(net_dev);
	return 0;
}

static int handle_en_event(struct net_device *netdev,
			   struct hns_roce_dev *hr_dev,
			   u32 port, unsigned long event)
{
	struct ib_device *ibdev = &hr_dev->ib_dev;
	struct device *dev = hr_dev->dev;
	enum ib_port_state curr_state;
	struct ib_event ibevent;
	int ret = 0;

	if (!netdev) {
		dev_err(dev, "can't find netdev on port(%u)!\n", port);
		return -ENODEV;
	}

	switch (event) {
	case NETDEV_REGISTER:
	case NETDEV_CHANGEADDR:
		ret = hns_roce_set_mac(hr_dev, port, netdev->dev_addr);
		break;
	case NETDEV_UP:
	case NETDEV_CHANGE:
		ret = hns_roce_set_mac(hr_dev, port, netdev->dev_addr);
		if (ret)
			return ret;
		fallthrough;
	case NETDEV_DOWN:
		if (!netif_is_lag_master(netdev))
			break;
		curr_state = ib_get_curr_port_state(netdev);

		write_lock_irq(&ibdev->cache_lock);
		if (ibdev->port_data[port].cache.last_port_state == curr_state) {
			write_unlock_irq(&ibdev->cache_lock);
			return 0;
		}
		ibdev->port_data[port].cache.last_port_state = curr_state;
		write_unlock_irq(&ibdev->cache_lock);

		ibevent.event = (curr_state == IB_PORT_DOWN) ?
				IB_EVENT_PORT_ERR : IB_EVENT_PORT_ACTIVE;
		ibevent.device = ibdev;
		ibevent.element.port_num = port + 1;
		ib_dispatch_event(&ibevent);
		break;
	default:
		dev_dbg(dev, "NETDEV event = 0x%x!\n", (u32)(event));
		break;
	}

	return ret;
}

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;
	u32 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(get_hr_netdev(hr_dev, 0),
						 get_hr_bus_num(hr_dev));
		upper = bond_grp ? bond_grp->upper_dev : NULL;
	}

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

Annotation

Implementation Notes