[PATCH 3/3] RDMA/core: Get all the ib devices from net devices

Zhu Yanjun
2022-10-23T05:39:40Z

From: Zhu Yanjun <yanjun.zhu@linux.dev>

To mlx4/5, the function ib_device_get_by_netdev can not get
ib devices from net devices.

So this function parses all the ib devices to get all the net
devices, then compares the net devices with the given net device.

Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
---
drivers/infiniband/core/device.c | 39 ++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index d38eb1fc2ed7..55e2d75d752e 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -2740,14 +2740,49 @@ int ib_dma_virt_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents)
EXPORT_SYMBOL(ib_dma_virt_map_sg);
#endif /* CONFIG_INFINIBAND_VIRT_DMA */

+static struct ib_device *get_ibdev_from_ndev(struct net_device *ndev)
+{
+ unsigned long index;
+ struct ib_device *dev;
+ int i;
+
+ down_read(&devices_rwsem);
+ xa_for_each_marked(&devices, index, dev, DEVICE_REGISTERED) {
+ if (!dev->ops.get_netdev)
+ continue;
+
+ for (i = 0; i < dev->phys_port_cnt; i++) {
+ struct net_device *netdev;
+
+ netdev = dev->ops.get_netdev(dev, i+1);
+ if (!netdev)
+ continue;
+
+ dev_put(netdev);
+ if (ndev == netdev) {
+ up_read(&devices_rwsem);
+ if (!ib_device_try_get(dev))
+ dev = NULL;
+ return dev;
+ }
+ }
+ }
+ up_read(&devices_rwsem);
+ return NULL;
+}
+
static int rdma_netns_notify(struct notifier_block *not_blk,
unsigned long event, void *arg)
{
struct net_device *ndev = netdev_notifier_info_to_dev(arg);
struct ib_device *ibdev = ib_device_get_by_netdev(ndev, RDMA_DRIVER_UNKNOWN);

- if (!ibdev)
- return NOTIFY_OK;
+ if (!ibdev) {
+ /* This is for MLX4/5 */
+ ibdev = get_ibdev_from_ndev(ndev);
+ if (!ibdev)
+ return NOTIFY_OK;
+ }

/* This will exclude IB device */
if (rdma_protocol_ib(ibdev, rdma_start_port(ibdev))) {
--
2.27.0