18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
28c2ecf20Sopenharmony_ci/* Copyright (c) 2020 Mellanox Technologies Ltd. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/module.h>
58c2ecf20Sopenharmony_ci#include <linux/mlx5/driver.h>
68c2ecf20Sopenharmony_ci#include <linux/mlx5/device.h>
78c2ecf20Sopenharmony_ci#include "mlx5_vdpa_ifc.h"
88c2ecf20Sopenharmony_ci#include "mlx5_vnet.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ciMODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
118c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Mellanox VDPA driver");
128c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic bool required_caps_supported(struct mlx5_core_dev *mdev)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	u8 event_mode;
178c2ecf20Sopenharmony_ci	u64 got;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	got = MLX5_CAP_GEN_64(mdev, general_obj_types);
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	if (!(got & MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q))
228c2ecf20Sopenharmony_ci		return false;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	event_mode = MLX5_CAP_DEV_VDPA_EMULATION(mdev, event_mode);
258c2ecf20Sopenharmony_ci	if (!(event_mode & MLX5_VIRTIO_Q_EVENT_MODE_QP_MODE))
268c2ecf20Sopenharmony_ci		return false;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	if (!MLX5_CAP_DEV_VDPA_EMULATION(mdev, eth_frame_offload_type))
298c2ecf20Sopenharmony_ci		return false;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	return true;
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic void *mlx5_vdpa_add(struct mlx5_core_dev *mdev)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	struct mlx5_vdpa_dev *vdev;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	if (mlx5_core_is_pf(mdev))
398c2ecf20Sopenharmony_ci		return NULL;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	if (!required_caps_supported(mdev)) {
428c2ecf20Sopenharmony_ci		dev_info(mdev->device, "virtio net emulation not supported\n");
438c2ecf20Sopenharmony_ci		return NULL;
448c2ecf20Sopenharmony_ci	}
458c2ecf20Sopenharmony_ci	vdev = mlx5_vdpa_add_dev(mdev);
468c2ecf20Sopenharmony_ci	if (IS_ERR(vdev))
478c2ecf20Sopenharmony_ci		return NULL;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	return vdev;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic void mlx5_vdpa_remove(struct mlx5_core_dev *mdev, void *context)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	struct mlx5_vdpa_dev *vdev = context;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	mlx5_vdpa_remove_dev(vdev);
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic struct mlx5_interface mlx5_vdpa_interface = {
608c2ecf20Sopenharmony_ci	.add = mlx5_vdpa_add,
618c2ecf20Sopenharmony_ci	.remove = mlx5_vdpa_remove,
628c2ecf20Sopenharmony_ci	.protocol = MLX5_INTERFACE_PROTOCOL_VDPA,
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic int __init mlx5_vdpa_init(void)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	return mlx5_register_interface(&mlx5_vdpa_interface);
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic void __exit mlx5_vdpa_exit(void)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	mlx5_unregister_interface(&mlx5_vdpa_interface);
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cimodule_init(mlx5_vdpa_init);
768c2ecf20Sopenharmony_cimodule_exit(mlx5_vdpa_exit);
77