RDMA/core: Get IB width and speed from netdev
authorHaoyue Xu <xuhaoyue1@hisilicon.com>
Fri, 21 Jul 2023 09:20:52 +0000 (17:20 +0800)
committerLeon Romanovsky <leon@kernel.org>
Sun, 30 Jul 2023 11:55:37 +0000 (14:55 +0300)
Previously, there was no way to query the number of lanes for a network
card, so the same netdev_speed would result in a fixed pair of width and
speed. As network card specifications become more diverse, such fixed
mode is no longer suitable, so a method is needed to obtain the correct
width and speed based on the number of lanes.

This patch retrieves netdev lanes and speed from net_device and
translates them to IB width and speed.

Signed-off-by: Haoyue Xu <xuhaoyue1@hisilicon.com>
Signed-off-by: Luoyouming <luoyouming@huawei.com>
Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
Link: https://lore.kernel.org/r/20230721092052.2090449-1-huangjunxian6@hisilicon.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/core/verbs.c

index b99b3cc..25367bd 100644 (file)
@@ -1880,6 +1880,80 @@ int ib_modify_qp_with_udata(struct ib_qp *ib_qp, struct ib_qp_attr *attr,
 }
 EXPORT_SYMBOL(ib_modify_qp_with_udata);
 
+static void ib_get_width_and_speed(u32 netdev_speed, u32 lanes,
+                                  u16 *speed, u8 *width)
+{
+       if (!lanes) {
+               if (netdev_speed <= SPEED_1000) {
+                       *width = IB_WIDTH_1X;
+                       *speed = IB_SPEED_SDR;
+               } else if (netdev_speed <= SPEED_10000) {
+                       *width = IB_WIDTH_1X;
+                       *speed = IB_SPEED_FDR10;
+               } else if (netdev_speed <= SPEED_20000) {
+                       *width = IB_WIDTH_4X;
+                       *speed = IB_SPEED_DDR;
+               } else if (netdev_speed <= SPEED_25000) {
+                       *width = IB_WIDTH_1X;
+                       *speed = IB_SPEED_EDR;
+               } else if (netdev_speed <= SPEED_40000) {
+                       *width = IB_WIDTH_4X;
+                       *speed = IB_SPEED_FDR10;
+               } else {
+                       *width = IB_WIDTH_4X;
+                       *speed = IB_SPEED_EDR;
+               }
+
+               return;
+       }
+
+       switch (lanes) {
+       case 1:
+               *width = IB_WIDTH_1X;
+               break;
+       case 2:
+               *width = IB_WIDTH_2X;
+               break;
+       case 4:
+               *width = IB_WIDTH_4X;
+               break;
+       case 8:
+               *width = IB_WIDTH_8X;
+               break;
+       case 12:
+               *width = IB_WIDTH_12X;
+               break;
+       default:
+               *width = IB_WIDTH_1X;
+       }
+
+       switch (netdev_speed / lanes) {
+       case SPEED_2500:
+               *speed = IB_SPEED_SDR;
+               break;
+       case SPEED_5000:
+               *speed = IB_SPEED_DDR;
+               break;
+       case SPEED_10000:
+               *speed = IB_SPEED_FDR10;
+               break;
+       case SPEED_14000:
+               *speed = IB_SPEED_FDR;
+               break;
+       case SPEED_25000:
+               *speed = IB_SPEED_EDR;
+               break;
+       case SPEED_50000:
+               *speed = IB_SPEED_HDR;
+               break;
+       case SPEED_100000:
+               *speed = IB_SPEED_NDR;
+               break;
+       default:
+               *speed = IB_SPEED_SDR;
+       }
+}
+
 int ib_get_eth_speed(struct ib_device *dev, u32 port_num, u16 *speed, u8 *width)
 {
        int rc;
@@ -1904,29 +1978,13 @@ int ib_get_eth_speed(struct ib_device *dev, u32 port_num, u16 *speed, u8 *width)
                netdev_speed = lksettings.base.speed;
        } else {
                netdev_speed = SPEED_1000;
-               pr_warn("%s speed is unknown, defaulting to %u\n", netdev->name,
-                       netdev_speed);
+               if (rc)
+                       pr_warn("%s speed is unknown, defaulting to %u\n",
+                               netdev->name, netdev_speed);
        }
 
-       if (netdev_speed <= SPEED_1000) {
-               *width = IB_WIDTH_1X;
-               *speed = IB_SPEED_SDR;
-       } else if (netdev_speed <= SPEED_10000) {
-               *width = IB_WIDTH_1X;
-               *speed = IB_SPEED_FDR10;
-       } else if (netdev_speed <= SPEED_20000) {
-               *width = IB_WIDTH_4X;
-               *speed = IB_SPEED_DDR;
-       } else if (netdev_speed <= SPEED_25000) {
-               *width = IB_WIDTH_1X;
-               *speed = IB_SPEED_EDR;
-       } else if (netdev_speed <= SPEED_40000) {
-               *width = IB_WIDTH_4X;
-               *speed = IB_SPEED_FDR10;
-       } else {
-               *width = IB_WIDTH_4X;
-               *speed = IB_SPEED_EDR;
-       }
+       ib_get_width_and_speed(netdev_speed, lksettings.lanes,
+                              speed, width);
 
        return 0;
 }