Commit bee35b71 authored by Long Li's avatar Long Li Committed by Leon Romanovsky
Browse files

RDMA/mana_ib: Handle net event for pointing to the current netdev



When running under Hyper-V, the master device to the RDMA device is always
bonded to this RDMA device. This is not user-configurable.

The master device can be unbind/bind from the kernel. During those events,
the RDMA device should set to the current netdev to reflect the change of
master device from those events.

Signed-off-by: default avatarLong Li <longli@microsoft.com>
Link: https://patch.msgid.link/1741821332-9392-2-git-send-email-longli@linuxonhyperv.com


Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent a8445cfe
Loading
Loading
Loading
Loading
+45 −2
Original line number Diff line number Diff line
@@ -65,6 +65,38 @@ static const struct ib_device_ops mana_ib_stats_ops = {
	.get_hw_stats = mana_ib_get_hw_stats,
};

static int mana_ib_netdev_event(struct notifier_block *this,
				unsigned long event, void *ptr)
{
	struct mana_ib_dev *dev = container_of(this, struct mana_ib_dev, nb);
	struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
	struct gdma_context *gc = dev->gdma_dev->gdma_context;
	struct mana_context *mc = gc->mana.driver_data;
	struct net_device *ndev;

	/* Only process events from our parent device */
	if (event_dev != mc->ports[0])
		return NOTIFY_DONE;

	switch (event) {
	case NETDEV_CHANGEUPPER:
		ndev = mana_get_primary_netdev(mc, 0, &dev->dev_tracker);
		/*
		 * RDMA core will setup GID based on updated netdev.
		 * It's not possible to race with the core as rtnl lock is being
		 * held.
		 */
		ib_device_set_netdev(&dev->ib_dev, ndev, 1);

		/* mana_get_primary_netdev() returns ndev with refcount held */
		netdev_put(ndev, &dev->dev_tracker);

		return NOTIFY_OK;
	default:
		return NOTIFY_DONE;
	}
}

static int mana_ib_probe(struct auxiliary_device *adev,
			 const struct auxiliary_device_id *id)
{
@@ -122,11 +154,19 @@ static int mana_ib_probe(struct auxiliary_device *adev,
	}
	dev->gdma_dev = &mdev->gdma_context->mana_ib;

	dev->nb.notifier_call = mana_ib_netdev_event;
	ret = register_netdevice_notifier(&dev->nb);
	if (ret) {
		ibdev_err(&dev->ib_dev, "Failed to register net notifier, %d",
			  ret);
		goto deregister_device;
	}

	ret = mana_ib_gd_query_adapter_caps(dev);
	if (ret) {
		ibdev_err(&dev->ib_dev, "Failed to query device caps, ret %d",
			  ret);
		goto deregister_device;
		goto deregister_net_notifier;
	}

	ib_set_device_ops(&dev->ib_dev, &mana_ib_stats_ops);
@@ -134,7 +174,7 @@ static int mana_ib_probe(struct auxiliary_device *adev,
	ret = mana_ib_create_eqs(dev);
	if (ret) {
		ibdev_err(&dev->ib_dev, "Failed to create EQs, ret %d", ret);
		goto deregister_device;
		goto deregister_net_notifier;
	}

	ret = mana_ib_gd_create_rnic_adapter(dev);
@@ -172,6 +212,8 @@ static int mana_ib_probe(struct auxiliary_device *adev,
	mana_ib_gd_destroy_rnic_adapter(dev);
destroy_eqs:
	mana_ib_destroy_eqs(dev);
deregister_net_notifier:
	unregister_netdevice_notifier(&dev->nb);
deregister_device:
	mana_gd_deregister_device(dev->gdma_dev);
free_ib_device:
@@ -188,6 +230,7 @@ static void mana_ib_remove(struct auxiliary_device *adev)
	xa_destroy(&dev->qp_table_wq);
	mana_ib_gd_destroy_rnic_adapter(dev);
	mana_ib_destroy_eqs(dev);
	unregister_netdevice_notifier(&dev->nb);
	mana_gd_deregister_device(dev->gdma_dev);
	ib_dealloc_device(&dev->ib_dev);
}
+1 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ struct mana_ib_dev {
	struct mana_ib_adapter_caps adapter_caps;
	struct dma_pool *av_pool;
	netdevice_tracker dev_tracker;
	struct notifier_block nb;
};

struct mana_ib_wq {