1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* Copyright (c) 2020 Mellanox Technologies Ltd */ 3 4 #include <linux/mlx5/driver.h> 5 #include <linux/mlx5/device.h> 6 #include <linux/mlx5/eswitch.h> 7 #include "mlx5_core.h" 8 #include "dev.h" 9 #include "devlink.h" 10 11 static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id) 12 { 13 struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev); 14 struct mlx5_core_dev *mdev; 15 struct devlink *devlink; 16 int err; 17 18 devlink = mlx5_devlink_alloc(&adev->dev); 19 if (!devlink) 20 return -ENOMEM; 21 22 mdev = devlink_priv(devlink); 23 mdev->device = &adev->dev; 24 mdev->pdev = sf_dev->parent_mdev->pdev; 25 mdev->bar_addr = sf_dev->bar_base_addr; 26 mdev->iseg_base = sf_dev->bar_base_addr; 27 mdev->coredev_type = MLX5_COREDEV_SF; 28 mdev->priv.parent_mdev = sf_dev->parent_mdev; 29 mdev->priv.adev_idx = adev->id; 30 sf_dev->mdev = mdev; 31 32 /* Only local SFs do light probe */ 33 if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev)) 34 mlx5_dev_set_lightweight(mdev); 35 36 err = mlx5_mdev_init(mdev, MLX5_SF_PROF); 37 if (err) { 38 mlx5_core_warn(mdev, "mlx5_mdev_init on err=%d\n", err); 39 goto mdev_err; 40 } 41 42 mdev->iseg = ioremap(mdev->iseg_base, sizeof(*mdev->iseg)); 43 if (!mdev->iseg) { 44 mlx5_core_warn(mdev, "remap error\n"); 45 err = -ENOMEM; 46 goto remap_err; 47 } 48 49 if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev)) 50 err = mlx5_init_one_light(mdev); 51 else 52 err = mlx5_init_one(mdev); 53 if (err) { 54 mlx5_core_warn(mdev, "mlx5_init_one err=%d\n", err); 55 goto init_one_err; 56 } 57 devlink_register(devlink); 58 return 0; 59 60 init_one_err: 61 iounmap(mdev->iseg); 62 remap_err: 63 mlx5_mdev_uninit(mdev); 64 mdev_err: 65 mlx5_devlink_free(devlink); 66 return err; 67 } 68 69 static void mlx5_sf_dev_remove(struct auxiliary_device *adev) 70 { 71 struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev); 72 struct devlink *devlink = priv_to_devlink(sf_dev->mdev); 73 74 mlx5_drain_health_wq(sf_dev->mdev); 75 devlink_unregister(devlink); 76 if (mlx5_dev_is_lightweight(sf_dev->mdev)) 77 mlx5_uninit_one_light(sf_dev->mdev); 78 else 79 mlx5_uninit_one(sf_dev->mdev); 80 iounmap(sf_dev->mdev->iseg); 81 mlx5_mdev_uninit(sf_dev->mdev); 82 mlx5_devlink_free(devlink); 83 } 84 85 static void mlx5_sf_dev_shutdown(struct auxiliary_device *adev) 86 { 87 struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev); 88 89 mlx5_unload_one(sf_dev->mdev, false); 90 } 91 92 static const struct auxiliary_device_id mlx5_sf_dev_id_table[] = { 93 { .name = MLX5_ADEV_NAME "." MLX5_SF_DEV_ID_NAME, }, 94 { }, 95 }; 96 97 MODULE_DEVICE_TABLE(auxiliary, mlx5_sf_dev_id_table); 98 99 static struct auxiliary_driver mlx5_sf_driver = { 100 .name = MLX5_SF_DEV_ID_NAME, 101 .probe = mlx5_sf_dev_probe, 102 .remove = mlx5_sf_dev_remove, 103 .shutdown = mlx5_sf_dev_shutdown, 104 .id_table = mlx5_sf_dev_id_table, 105 }; 106 107 int mlx5_sf_driver_register(void) 108 { 109 return auxiliary_driver_register(&mlx5_sf_driver); 110 } 111 112 void mlx5_sf_driver_unregister(void) 113 { 114 auxiliary_driver_unregister(&mlx5_sf_driver); 115 } 116