struct mlx5_core_dev *dev = devlink_priv(devlink);
        bool new_state = val.vbool;
 
-       if (new_state && !MLX5_CAP_GEN(dev, roce)) {
+       if (new_state && !MLX5_CAP_GEN(dev, roce) &&
+           !MLX5_CAP_GEN(dev, roce_rw_supported)) {
                NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE");
                return -EOPNOTSUPP;
        }
 
                MLX5_SET(cmd_hca_cap, set_hca_cap, num_total_dynamic_vf_msix,
                         MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix));
 
+       if (MLX5_CAP_GEN(dev, roce_rw_supported))
+               MLX5_SET(cmd_hca_cap, set_hca_cap, roce, mlx5_is_roce_init_enabled(dev));
+
        return set_caps(dev, set_ctx, MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE);
 }
 
+/* Cached MLX5_CAP_GEN(dev, roce) can be out of sync this early in the
+ * boot process.
+ * In case RoCE cap is writable in FW and user/devlink requested to change the
+ * cap, we are yet to query the final state of the above cap.
+ * Hence, the need for this function.
+ *
+ * Returns
+ * True:
+ * 1) RoCE cap is read only in FW and already disabled
+ * OR:
+ * 2) RoCE cap is writable in FW and user/devlink requested it off.
+ *
+ * In any other case, return False.
+ */
+static bool is_roce_fw_disabled(struct mlx5_core_dev *dev)
+{
+       return (MLX5_CAP_GEN(dev, roce_rw_supported) && !mlx5_is_roce_init_enabled(dev)) ||
+               (!MLX5_CAP_GEN(dev, roce_rw_supported) && !MLX5_CAP_GEN(dev, roce));
+}
+
 static int handle_hca_cap_roce(struct mlx5_core_dev *dev, void *set_ctx)
 {
        void *set_hca_cap;
        int err;
 
-       if (!MLX5_CAP_GEN(dev, roce))
+       if (is_roce_fw_disabled(dev))
                return 0;
 
        err = mlx5_core_get_caps(dev, MLX5_CAP_ROCE);
 
 {
        struct devlink *devlink = priv_to_devlink(dev);
        union devlink_param_value val;
+       int err;
 
-       devlink_param_driverinit_value_get(devlink,
-                                          DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
-                                          &val);
-       return val.vbool;
+       err = devlink_param_driverinit_value_get(devlink,
+                                                DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
+                                                &val);
+       return err ? MLX5_CAP_GEN(dev, roce) : val.vbool;
 }
 
 #endif /* MLX5_DRIVER_H */
 
        u8         log_max_tis_per_sq[0x5];
 
        u8         ext_stride_num_range[0x1];
-       u8         reserved_at_3a1[0x2];
+       u8         roce_rw_supported[0x1];
+       u8         reserved_at_3a2[0x1];
        u8         log_max_stride_sz_rq[0x5];
        u8         reserved_at_3a8[0x3];
        u8         log_min_stride_sz_rq[0x5];