RDMA/mlx4: Do not fail the registration on port stats
authorJack Wang <jinpu.wang@ionos.com>
Mon, 15 Nov 2021 10:15:19 +0000 (11:15 +0100)
committerJason Gunthorpe <jgg@nvidia.com>
Wed, 17 Nov 2021 20:45:16 +0000 (16:45 -0400)
If the FW doesn't support MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT, mlx4 driver
will fail the ib_setup_port_attrs, which is called from
ib_register_device()/enable_device_and_get(), in the end leads to device
not detected[1][2]

To fix it, add a new mlx4_ib_hw_stats_ops1, w/o alloc_hw_port_stats if FW
does not support MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=2014094
[2] https://lore.kernel.org/linux-rdma/CAMGffEn2wvEnmzc0xe=xYiCLqpphiHDBxCxqAELrBofbUAMQxw@mail.gmail.com

Fixes: 4b5f4d3fb408 ("RDMA: Split the alloc_hw_stats() ops to port and device variants")
Link: https://lore.kernel.org/r/20211115101519.27210-1-jinpu.wang@ionos.com
Signed-off-by: Jack Wang <jinpu.wang@ionos.com>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/hw/mlx4/main.c

index ceca059..0d2fa33 100644 (file)
@@ -2215,6 +2215,11 @@ static const struct ib_device_ops mlx4_ib_hw_stats_ops = {
        .get_hw_stats = mlx4_ib_get_hw_stats,
 };
 
+static const struct ib_device_ops mlx4_ib_hw_stats_ops1 = {
+       .alloc_hw_device_stats = mlx4_ib_alloc_hw_device_stats,
+       .get_hw_stats = mlx4_ib_get_hw_stats,
+};
+
 static int mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev)
 {
        struct mlx4_ib_diag_counters *diag = ibdev->diag_counters;
@@ -2227,9 +2232,16 @@ static int mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev)
                return 0;
 
        for (i = 0; i < MLX4_DIAG_COUNTERS_TYPES; i++) {
-               /* i == 1 means we are building port counters */
-               if (i && !per_port)
-                       continue;
+               /*
+                * i == 1 means we are building port counters, set a different
+                * stats ops without port stats callback.
+                */
+               if (i && !per_port) {
+                       ib_set_device_ops(&ibdev->ib_dev,
+                                         &mlx4_ib_hw_stats_ops1);
+
+                       return 0;
+               }
 
                ret = __mlx4_ib_alloc_diag_counters(ibdev, &diag[i].descs,
                                                    &diag[i].offset,