Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mlx4: Register mlx4 devices to an auxiliary virtual bus

Add an auxiliary virtual bus to model the mlx4 driver structure. The
code is added along the current custom device management logic.
Subsequent patches switch mlx4_en and mlx4_ib to the auxiliary bus and
the old interface is then removed.

Structure mlx4_priv gains a new adev dynamic array to keep track of its
auxiliary devices. Access to the array is protected by the global
mlx4_intf mutex.

Functions mlx4_register_device() and mlx4_unregister_device() are
updated to expose auxiliary devices on the bus in order to load mlx4_en
and/or mlx4_ib. Functions mlx4_register_auxiliary_driver() and
mlx4_unregister_auxiliary_driver() are added to substitute
mlx4_register_interface() and mlx4_unregister_interface(), respectively.
Function mlx4_do_bond() is adjusted to walk over the adev array and
re-adds a specific auxiliary device if its driver sets the
MLX4_INTFF_BONDING flag.

Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
Tested-by: Leon Romanovsky <leonro@nvidia.com>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Acked-by: Tariq Toukan <tariqt@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Petr Pavlu and committed by
David S. Miller
8c2d2b87 c9452b8f

+268 -4
+1
drivers/net/ethernet/mellanox/mlx4/Kconfig
··· 27 27 config MLX4_CORE 28 28 tristate 29 29 depends on PCI 30 + select AUXILIARY_BUS 30 31 select NET_DEVLINK 31 32 default n 32 33
+228 -2
drivers/net/ethernet/mellanox/mlx4/intf.c
··· 48 48 static LIST_HEAD(intf_list); 49 49 static LIST_HEAD(dev_list); 50 50 static DEFINE_MUTEX(intf_mutex); 51 + static DEFINE_IDA(mlx4_adev_ida); 52 + 53 + static const struct mlx4_adev_device { 54 + const char *suffix; 55 + bool (*is_supported)(struct mlx4_dev *dev); 56 + } mlx4_adev_devices[1] = {}; 57 + 58 + int mlx4_adev_init(struct mlx4_dev *dev) 59 + { 60 + struct mlx4_priv *priv = mlx4_priv(dev); 61 + 62 + priv->adev_idx = ida_alloc(&mlx4_adev_ida, GFP_KERNEL); 63 + if (priv->adev_idx < 0) 64 + return priv->adev_idx; 65 + 66 + priv->adev = kcalloc(ARRAY_SIZE(mlx4_adev_devices), 67 + sizeof(struct mlx4_adev *), GFP_KERNEL); 68 + if (!priv->adev) { 69 + ida_free(&mlx4_adev_ida, priv->adev_idx); 70 + return -ENOMEM; 71 + } 72 + 73 + return 0; 74 + } 75 + 76 + void mlx4_adev_cleanup(struct mlx4_dev *dev) 77 + { 78 + struct mlx4_priv *priv = mlx4_priv(dev); 79 + 80 + kfree(priv->adev); 81 + ida_free(&mlx4_adev_ida, priv->adev_idx); 82 + } 83 + 84 + static void adev_release(struct device *dev) 85 + { 86 + struct mlx4_adev *mlx4_adev = 87 + container_of(dev, struct mlx4_adev, adev.dev); 88 + struct mlx4_priv *priv = mlx4_priv(mlx4_adev->mdev); 89 + int idx = mlx4_adev->idx; 90 + 91 + kfree(mlx4_adev); 92 + priv->adev[idx] = NULL; 93 + } 94 + 95 + static struct mlx4_adev *add_adev(struct mlx4_dev *dev, int idx) 96 + { 97 + struct mlx4_priv *priv = mlx4_priv(dev); 98 + const char *suffix = mlx4_adev_devices[idx].suffix; 99 + struct auxiliary_device *adev; 100 + struct mlx4_adev *madev; 101 + int ret; 102 + 103 + madev = kzalloc(sizeof(*madev), GFP_KERNEL); 104 + if (!madev) 105 + return ERR_PTR(-ENOMEM); 106 + 107 + adev = &madev->adev; 108 + adev->id = priv->adev_idx; 109 + adev->name = suffix; 110 + adev->dev.parent = &dev->persist->pdev->dev; 111 + adev->dev.release = adev_release; 112 + madev->mdev = dev; 113 + madev->idx = idx; 114 + 115 + ret = auxiliary_device_init(adev); 116 + if (ret) { 117 + kfree(madev); 118 + return ERR_PTR(ret); 119 + } 120 + 121 + ret = auxiliary_device_add(adev); 122 + if (ret) { 123 + auxiliary_device_uninit(adev); 124 + return ERR_PTR(ret); 125 + } 126 + return madev; 127 + } 128 + 129 + static void del_adev(struct auxiliary_device *adev) 130 + { 131 + auxiliary_device_delete(adev); 132 + auxiliary_device_uninit(adev); 133 + } 51 134 52 135 static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv) 53 136 { ··· 203 120 } 204 121 EXPORT_SYMBOL_GPL(mlx4_unregister_interface); 205 122 123 + int mlx4_register_auxiliary_driver(struct mlx4_adrv *madrv) 124 + { 125 + return auxiliary_driver_register(&madrv->adrv); 126 + } 127 + EXPORT_SYMBOL_GPL(mlx4_register_auxiliary_driver); 128 + 129 + void mlx4_unregister_auxiliary_driver(struct mlx4_adrv *madrv) 130 + { 131 + auxiliary_driver_unregister(&madrv->adrv); 132 + } 133 + EXPORT_SYMBOL_GPL(mlx4_unregister_auxiliary_driver); 134 + 206 135 int mlx4_do_bond(struct mlx4_dev *dev, bool enable) 207 136 { 208 137 struct mlx4_priv *priv = mlx4_priv(dev); 209 138 struct mlx4_device_context *dev_ctx = NULL, *temp_dev_ctx; 210 139 unsigned long flags; 211 - int ret; 140 + int i, ret; 212 141 LIST_HEAD(bond_list); 213 142 214 143 if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PORT_REMAP)) ··· 272 177 dev_ctx->intf->protocol, enable ? 273 178 "enabled" : "disabled"); 274 179 } 180 + 181 + mutex_lock(&intf_mutex); 182 + 183 + for (i = 0; i < ARRAY_SIZE(mlx4_adev_devices); i++) { 184 + struct mlx4_adev *madev = priv->adev[i]; 185 + struct mlx4_adrv *madrv; 186 + enum mlx4_protocol protocol; 187 + 188 + if (!madev) 189 + continue; 190 + 191 + device_lock(&madev->adev.dev); 192 + if (!madev->adev.dev.driver) { 193 + device_unlock(&madev->adev.dev); 194 + continue; 195 + } 196 + 197 + madrv = container_of(madev->adev.dev.driver, struct mlx4_adrv, 198 + adrv.driver); 199 + if (!(madrv->flags & MLX4_INTFF_BONDING)) { 200 + device_unlock(&madev->adev.dev); 201 + continue; 202 + } 203 + 204 + if (mlx4_is_mfunc(dev)) { 205 + mlx4_dbg(dev, 206 + "SRIOV, disabled HA mode for intf proto %d\n", 207 + madrv->protocol); 208 + device_unlock(&madev->adev.dev); 209 + continue; 210 + } 211 + 212 + protocol = madrv->protocol; 213 + device_unlock(&madev->adev.dev); 214 + 215 + del_adev(&madev->adev); 216 + priv->adev[i] = add_adev(dev, i); 217 + if (IS_ERR(priv->adev[i])) { 218 + mlx4_warn(dev, "Device[%d] (%s) failed to load\n", i, 219 + mlx4_adev_devices[i].suffix); 220 + priv->adev[i] = NULL; 221 + continue; 222 + } 223 + 224 + mlx4_dbg(dev, 225 + "Interface for protocol %d restarted with bonded mode %s\n", 226 + protocol, enable ? "enabled" : "disabled"); 227 + } 228 + 229 + mutex_unlock(&intf_mutex); 230 + 275 231 return 0; 276 232 } 277 233 ··· 352 206 } 353 207 EXPORT_SYMBOL(mlx4_unregister_event_notifier); 354 208 209 + static int add_drivers(struct mlx4_dev *dev) 210 + { 211 + struct mlx4_priv *priv = mlx4_priv(dev); 212 + int i, ret = 0; 213 + 214 + for (i = 0; i < ARRAY_SIZE(mlx4_adev_devices); i++) { 215 + bool is_supported = false; 216 + 217 + if (priv->adev[i]) 218 + continue; 219 + 220 + if (mlx4_adev_devices[i].is_supported) 221 + is_supported = mlx4_adev_devices[i].is_supported(dev); 222 + 223 + if (!is_supported) 224 + continue; 225 + 226 + priv->adev[i] = add_adev(dev, i); 227 + if (IS_ERR(priv->adev[i])) { 228 + mlx4_warn(dev, "Device[%d] (%s) failed to load\n", i, 229 + mlx4_adev_devices[i].suffix); 230 + /* We continue to rescan drivers and leave to the caller 231 + * to make decision if to release everything or 232 + * continue. */ 233 + ret = PTR_ERR(priv->adev[i]); 234 + priv->adev[i] = NULL; 235 + } 236 + } 237 + return ret; 238 + } 239 + 240 + static void delete_drivers(struct mlx4_dev *dev) 241 + { 242 + struct mlx4_priv *priv = mlx4_priv(dev); 243 + bool delete_all; 244 + int i; 245 + 246 + delete_all = !(dev->persist->interface_state & MLX4_INTERFACE_STATE_UP); 247 + 248 + for (i = ARRAY_SIZE(mlx4_adev_devices) - 1; i >= 0; i--) { 249 + bool is_supported = false; 250 + 251 + if (!priv->adev[i]) 252 + continue; 253 + 254 + if (mlx4_adev_devices[i].is_supported && !delete_all) 255 + is_supported = mlx4_adev_devices[i].is_supported(dev); 256 + 257 + if (is_supported) 258 + continue; 259 + 260 + del_adev(&priv->adev[i]->adev); 261 + priv->adev[i] = NULL; 262 + } 263 + } 264 + 265 + /* This function is used after mlx4_dev is reconfigured. 266 + */ 267 + static int rescan_drivers_locked(struct mlx4_dev *dev) 268 + { 269 + lockdep_assert_held(&intf_mutex); 270 + 271 + delete_drivers(dev); 272 + if (!(dev->persist->interface_state & MLX4_INTERFACE_STATE_UP)) 273 + return 0; 274 + 275 + return add_drivers(dev); 276 + } 277 + 355 278 int mlx4_register_device(struct mlx4_dev *dev) 356 279 { 357 280 struct mlx4_priv *priv = mlx4_priv(dev); 358 281 struct mlx4_interface *intf; 282 + int ret; 359 283 360 284 mutex_lock(&intf_mutex); 361 285 ··· 434 218 list_for_each_entry(intf, &intf_list, list) 435 219 mlx4_add_device(intf, priv); 436 220 221 + ret = rescan_drivers_locked(dev); 222 + 437 223 mutex_unlock(&intf_mutex); 224 + 225 + if (ret) { 226 + mlx4_unregister_device(dev); 227 + return ret; 228 + } 229 + 438 230 mlx4_start_catas_poll(dev); 439 231 440 - return 0; 232 + return ret; 441 233 } 442 234 443 235 void mlx4_unregister_device(struct mlx4_dev *dev) ··· 476 252 477 253 list_del(&priv->dev_list); 478 254 dev->persist->interface_state &= ~MLX4_INTERFACE_STATE_UP; 255 + 256 + rescan_drivers_locked(dev); 479 257 480 258 mutex_unlock(&intf_mutex); 481 259 }
+15 -2
drivers/net/ethernet/mellanox/mlx4/main.c
··· 3429 3429 INIT_LIST_HEAD(&priv->ctx_list); 3430 3430 spin_lock_init(&priv->ctx_lock); 3431 3431 3432 + err = mlx4_adev_init(dev); 3433 + if (err) 3434 + return err; 3435 + 3432 3436 ATOMIC_INIT_NOTIFIER_HEAD(&priv->event_nh); 3433 3437 3434 3438 mutex_init(&priv->port_mutex); ··· 3459 3455 err = mlx4_get_ownership(dev); 3460 3456 if (err) { 3461 3457 if (err < 0) 3462 - return err; 3458 + goto err_adev; 3463 3459 else { 3464 3460 mlx4_warn(dev, "Multiple PFs not yet supported - Skipping PF\n"); 3465 - return -EINVAL; 3461 + err = -EINVAL; 3462 + goto err_adev; 3466 3463 } 3467 3464 } 3468 3465 ··· 3811 3806 mlx4_free_ownership(dev); 3812 3807 3813 3808 kfree(dev_cap); 3809 + 3810 + err_adev: 3811 + mlx4_adev_cleanup(dev); 3814 3812 return err; 3815 3813 } 3816 3814 ··· 4193 4185 4194 4186 mlx4_slave_destroy_special_qp_cap(dev); 4195 4187 kfree(dev->dev_vfs); 4188 + 4189 + mlx4_adev_cleanup(dev); 4196 4190 4197 4191 mlx4_clean_dev(dev); 4198 4192 priv->pci_dev_data = pci_dev_data; ··· 4582 4572 static int __init mlx4_init(void) 4583 4573 { 4584 4574 int ret; 4575 + 4576 + WARN_ONCE(strcmp(MLX4_ADEV_NAME, KBUILD_MODNAME), 4577 + "mlx4_core name not in sync with kernel module name"); 4585 4578 4586 4579 if (mlx4_verify_params()) 4587 4580 return -EINVAL;
+6
drivers/net/ethernet/mellanox/mlx4/mlx4.h
··· 47 47 #include <linux/spinlock.h> 48 48 #include <net/devlink.h> 49 49 #include <linux/rwsem.h> 50 + #include <linux/auxiliary_bus.h> 50 51 #include <linux/notifier.h> 51 52 52 53 #include <linux/mlx4/device.h> ··· 885 884 struct list_head dev_list; 886 885 struct list_head ctx_list; 887 886 spinlock_t ctx_lock; 887 + struct mlx4_adev **adev; 888 + int adev_idx; 888 889 struct atomic_notifier_head event_nh; 889 890 890 891 int pci_dev_data; ··· 1055 1052 int mlx4_crdump_init(struct mlx4_dev *dev); 1056 1053 void mlx4_crdump_end(struct mlx4_dev *dev); 1057 1054 int mlx4_restart_one(struct pci_dev *pdev); 1055 + 1056 + int mlx4_adev_init(struct mlx4_dev *dev); 1057 + void mlx4_adev_cleanup(struct mlx4_dev *dev); 1058 1058 int mlx4_register_device(struct mlx4_dev *dev); 1059 1059 void mlx4_unregister_device(struct mlx4_dev *dev); 1060 1060 void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type,
+7
include/linux/mlx4/device.h
··· 33 33 #ifndef MLX4_DEVICE_H 34 34 #define MLX4_DEVICE_H 35 35 36 + #include <linux/auxiliary_bus.h> 36 37 #include <linux/if_ether.h> 37 38 #include <linux/pci.h> 38 39 #include <linux/completion.h> ··· 888 887 u64 regid_allmulti_array[MLX4_MAX_PORTS + 1]; 889 888 struct mlx4_vf_dev *dev_vfs; 890 889 u8 uar_page_shift; 890 + }; 891 + 892 + struct mlx4_adev { 893 + struct auxiliary_device adev; 894 + struct mlx4_dev *mdev; 895 + int idx; 891 896 }; 892 897 893 898 struct mlx4_clock_params {
+11
include/linux/mlx4/driver.h
··· 34 34 #define MLX4_DRIVER_H 35 35 36 36 #include <net/devlink.h> 37 + #include <linux/auxiliary_bus.h> 37 38 #include <linux/notifier.h> 38 39 #include <linux/mlx4/device.h> 40 + 41 + #define MLX4_ADEV_NAME "mlx4_core" 39 42 40 43 struct mlx4_dev; 41 44 ··· 66 63 int flags; 67 64 }; 68 65 66 + struct mlx4_adrv { 67 + struct auxiliary_driver adrv; 68 + enum mlx4_protocol protocol; 69 + int flags; 70 + }; 71 + 69 72 int mlx4_register_interface(struct mlx4_interface *intf); 70 73 void mlx4_unregister_interface(struct mlx4_interface *intf); 74 + int mlx4_register_auxiliary_driver(struct mlx4_adrv *madrv); 75 + void mlx4_unregister_auxiliary_driver(struct mlx4_adrv *madrv); 71 76 72 77 int mlx4_register_event_notifier(struct mlx4_dev *dev, 73 78 struct notifier_block *nb);