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 mlx5_core_dev *mdev = sf_dev->mdev; 73 struct devlink *devlink; 74 75 devlink = priv_to_devlink(mdev); 76 set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state); 77 mlx5_drain_health_wq(mdev); 78 if (mlx5_dev_is_lightweight(mdev)) 79 mlx5_uninit_one_light(mdev); 80 else 81 mlx5_uninit_one(mdev); 82 iounmap(mdev->iseg); 83 mlx5_mdev_uninit(mdev); 84 mlx5_devlink_free(devlink); 85 } 86 87 static void mlx5_sf_dev_shutdown(struct auxiliary_device *adev) 88 { 89 struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev); 90 struct mlx5_core_dev *mdev = sf_dev->mdev; 91 92 set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state); 93 mlx5_unload_one(mdev, false); 94 } 95 96 static const struct auxiliary_device_id mlx5_sf_dev_id_table[] = { 97 { .name = MLX5_ADEV_NAME "." MLX5_SF_DEV_ID_NAME, }, 98 { }, 99 }; 100 101 MODULE_DEVICE_TABLE(auxiliary, mlx5_sf_dev_id_table); 102 103 static struct auxiliary_driver mlx5_sf_driver = { 104 .name = MLX5_SF_DEV_ID_NAME, 105 .probe = mlx5_sf_dev_probe, 106 .remove = mlx5_sf_dev_remove, 107 .shutdown = mlx5_sf_dev_shutdown, 108 .id_table = mlx5_sf_dev_id_table, 109 }; 110 111 int mlx5_sf_driver_register(void) 112 { 113 return auxiliary_driver_register(&mlx5_sf_driver); 114 } 115 116 void mlx5_sf_driver_unregister(void) 117 { 118 auxiliary_driver_unregister(&mlx5_sf_driver); 119 } 120