Commit 8e98387b authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'mlx5-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux

Saeed Mahameed says:

====================
mlx5-next auxbus support

This pull request is targeting net-next and rdma-next branches.

This series provides mlx5 support for auxiliary bus devices.

It starts with a merge commit of tag 'auxbus-5.11-rc1' from
gregkh/driver-core into mlx5-next, then the mlx5 patches that will convert
mlx5 ulp devices (netdev, rdma, vdpa) to use the proper auxbus
infrastructure instead of the internal mlx5 device and interface management
implementation, which Leon is deleting at the end of this patchset.

Link: https://lore.kernel.org/alsa-devel/20201026111849.1035786-1-leon@kernel.org/

Thanks to everyone for the joint effort !

* 'mlx5-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux:
  RDMA/mlx5: Remove IB representors dead code
  net/mlx5: Simplify eswitch mode check
  net/mlx5: Delete custom device management logic
  RDMA/mlx5: Convert mlx5_ib to use auxiliary bus
  net/mlx5e: Connect ethernet part to auxiliary bus
  vdpa/mlx5: Connect mlx5_vdpa to auxiliary bus
  net/mlx5: Register mlx5 devices to auxiliary virtual bus
  vdpa/mlx5: Make hardware definitions visible to all mlx5 devices
  net/mlx5_core: Clean driver version and name
  net/mlx5: Properly convey driver version to firmware
  driver core: auxiliary bus: minor coding style tweaks
  driver core: auxiliary bus: make remove function return void
  driver core: auxiliary bus: move slab.h from include file
  Add auxiliary bus support
====================

Link: https://lore.kernel.org/r/20201207053349.402772-1-saeed@kernel.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 374a96b9 04b222f9
This diff is collapsed.
......@@ -72,6 +72,7 @@ available subsections can be seen below.
thermal/index
fpga/index
acpi/index
auxiliary_bus
backlight/lp855x-driver.rst
connector
console
......
# SPDX-License-Identifier: GPL-2.0
menu "Generic Driver Options"
config AUXILIARY_BUS
bool
config UEVENT_HELPER
bool "Support for uevent helper"
help
......
......@@ -7,6 +7,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \
attribute_container.o transport_class.o \
topology.o container.o property.o cacheinfo.o \
swnode.o
obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o
obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
obj-y += power/
obj-$(CONFIG_ISA_BUS_API) += isa.o
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020 Intel Corporation
*
* Please see Documentation/driver-api/auxiliary_bus.rst for more information.
*/
#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
#include <linux/device.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/string.h>
#include <linux/auxiliary_bus.h>
static const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id,
const struct auxiliary_device *auxdev)
{
for (; id->name[0]; id++) {
const char *p = strrchr(dev_name(&auxdev->dev), '.');
int match_size;
if (!p)
continue;
match_size = p - dev_name(&auxdev->dev);
/* use dev_name(&auxdev->dev) prefix before last '.' char to match to */
if (strlen(id->name) == match_size &&
!strncmp(dev_name(&auxdev->dev), id->name, match_size))
return id;
}
return NULL;
}
static int auxiliary_match(struct device *dev, struct device_driver *drv)
{
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
struct auxiliary_driver *auxdrv = to_auxiliary_drv(drv);
return !!auxiliary_match_id(auxdrv->id_table, auxdev);
}
static int auxiliary_uevent(struct device *dev, struct kobj_uevent_env *env)
{
const char *name, *p;
name = dev_name(dev);
p = strrchr(name, '.');
return add_uevent_var(env, "MODALIAS=%s%.*s", AUXILIARY_MODULE_PREFIX,
(int)(p - name), name);
}
static const struct dev_pm_ops auxiliary_dev_pm_ops = {
SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
};
static int auxiliary_bus_probe(struct device *dev)
{
struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver);
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
int ret;
ret = dev_pm_domain_attach(dev, true);
if (ret) {
dev_warn(dev, "Failed to attach to PM Domain : %d\n", ret);
return ret;
}
ret = auxdrv->probe(auxdev, auxiliary_match_id(auxdrv->id_table, auxdev));
if (ret)
dev_pm_domain_detach(dev, true);
return ret;
}
static int auxiliary_bus_remove(struct device *dev)
{
struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver);
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
if (auxdrv->remove)
auxdrv->remove(auxdev);
dev_pm_domain_detach(dev, true);
return 0;
}
static void auxiliary_bus_shutdown(struct device *dev)
{
struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver);
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
if (auxdrv->shutdown)
auxdrv->shutdown(auxdev);
}
static struct bus_type auxiliary_bus_type = {
.name = "auxiliary",
.probe = auxiliary_bus_probe,
.remove = auxiliary_bus_remove,
.shutdown = auxiliary_bus_shutdown,
.match = auxiliary_match,
.uevent = auxiliary_uevent,
.pm = &auxiliary_dev_pm_ops,
};
/**
* auxiliary_device_init - check auxiliary_device and initialize
* @auxdev: auxiliary device struct
*
* This is the first step in the two-step process to register an
* auxiliary_device.
*
* When this function returns an error code, then the device_initialize will
* *not* have been performed, and the caller will be responsible to free any
* memory allocated for the auxiliary_device in the error path directly.
*
* It returns 0 on success. On success, the device_initialize has been
* performed. After this point any error unwinding will need to include a call
* to auxiliary_device_uninit(). In this post-initialize error scenario, a call
* to the device's .release callback will be triggered, and all memory clean-up
* is expected to be handled there.
*/
int auxiliary_device_init(struct auxiliary_device *auxdev)
{
struct device *dev = &auxdev->dev;
if (!dev->parent) {
pr_err("auxiliary_device has a NULL dev->parent\n");
return -EINVAL;
}
if (!auxdev->name) {
pr_err("auxiliary_device has a NULL name\n");
return -EINVAL;
}
dev->bus = &auxiliary_bus_type;
device_initialize(&auxdev->dev);
return 0;
}
EXPORT_SYMBOL_GPL(auxiliary_device_init);
/**
* __auxiliary_device_add - add an auxiliary bus device
* @auxdev: auxiliary bus device to add to the bus
* @modname: name of the parent device's driver module
*
* This is the second step in the two-step process to register an
* auxiliary_device.
*
* This function must be called after a successful call to
* auxiliary_device_init(), which will perform the device_initialize. This
* means that if this returns an error code, then a call to
* auxiliary_device_uninit() must be performed so that the .release callback
* will be triggered to free the memory associated with the auxiliary_device.
*
* The expectation is that users will call the "auxiliary_device_add" macro so
* that the caller's KBUILD_MODNAME is automatically inserted for the modname
* parameter. Only if a user requires a custom name would this version be
* called directly.
*/
int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname)
{
struct device *dev = &auxdev->dev;
int ret;
if (!modname) {
dev_err(dev, "auxiliary device modname is NULL\n");
return -EINVAL;
}
ret = dev_set_name(dev, "%s.%s.%d", modname, auxdev->name, auxdev->id);
if (ret) {
dev_err(dev, "auxiliary device dev_set_name failed: %d\n", ret);
return ret;
}
ret = device_add(dev);
if (ret)
dev_err(dev, "adding auxiliary device failed!: %d\n", ret);
return ret;
}
EXPORT_SYMBOL_GPL(__auxiliary_device_add);
/**
* auxiliary_find_device - auxiliary device iterator for locating a particular device.
* @start: Device to begin with
* @data: Data to pass to match function
* @match: Callback function to check device
*
* This function returns a reference to a device that is 'found'
* for later use, as determined by the @match callback.
*
* The callback should return 0 if the device doesn't match and non-zero
* if it does. If the callback returns non-zero, this function will
* return to the caller and not iterate over any more devices.
*/
struct auxiliary_device *auxiliary_find_device(struct device *start,
const void *data,
int (*match)(struct device *dev, const void *data))
{
struct device *dev;
dev = bus_find_device(&auxiliary_bus_type, start, data, match);
if (!dev)
return NULL;
return to_auxiliary_dev(dev);
}
EXPORT_SYMBOL_GPL(auxiliary_find_device);
/**
* __auxiliary_driver_register - register a driver for auxiliary bus devices
* @auxdrv: auxiliary_driver structure
* @owner: owning module/driver
* @modname: KBUILD_MODNAME for parent driver
*/
int __auxiliary_driver_register(struct auxiliary_driver *auxdrv,
struct module *owner, const char *modname)
{
if (WARN_ON(!auxdrv->probe) || WARN_ON(!auxdrv->id_table))
return -EINVAL;
if (auxdrv->name)
auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s.%s", modname,
auxdrv->name);
else
auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s", modname);
if (!auxdrv->driver.name)
return -ENOMEM;
auxdrv->driver.owner = owner;
auxdrv->driver.bus = &auxiliary_bus_type;
auxdrv->driver.mod_name = modname;
return driver_register(&auxdrv->driver);
}
EXPORT_SYMBOL_GPL(__auxiliary_driver_register);
/**
* auxiliary_driver_unregister - unregister a driver
* @auxdrv: auxiliary_driver structure
*/
void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv)
{
driver_unregister(&auxdrv->driver);
kfree(auxdrv->driver.name);
}
EXPORT_SYMBOL_GPL(auxiliary_driver_unregister);
static int __init auxiliary_bus_init(void)
{
return bus_register(&auxiliary_bus_type);
}
static void __exit auxiliary_bus_exit(void)
{
bus_unregister(&auxiliary_bus_type);
}
module_init(auxiliary_bus_init);
module_exit(auxiliary_bus_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Auxiliary Bus");
MODULE_AUTHOR("David Ertman <david.m.ertman@intel.com>");
MODULE_AUTHOR("Kiran Patil <kiran.patil@intel.com>");
......@@ -138,13 +138,6 @@ static int mlx5_ib_create_counters(struct ib_counters *counters,
}
static bool is_mdev_switchdev_mode(const struct mlx5_core_dev *mdev)
{
return MLX5_ESWITCH_MANAGER(mdev) &&
mlx5_ib_eswitch_mode(mdev->priv.eswitch) ==
MLX5_ESWITCH_OFFLOADS;
}
static const struct mlx5_ib_counters *get_counters(struct mlx5_ib_dev *dev,
u8 port_num)
{
......
......@@ -13,7 +13,7 @@ mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
struct mlx5_ib_dev *ibdev;
int vport_index;
ibdev = mlx5_ib_get_uplink_ibdev(dev->priv.eswitch);
ibdev = mlx5_eswitch_uplink_get_proto_dev(dev->priv.eswitch, REP_IB);
vport_index = rep->vport_index;
ibdev->port[vport_index].rep = rep;
......@@ -33,6 +33,7 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
const struct mlx5_ib_profile *profile;
struct mlx5_ib_dev *ibdev;
int vport_index;
int ret;
if (rep->vport == MLX5_VPORT_UPLINK)
profile = &raw_eth_profile;
......@@ -46,8 +47,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
ibdev->port = kcalloc(num_ports, sizeof(*ibdev->port),
GFP_KERNEL);
if (!ibdev->port) {
ib_dealloc_device(&ibdev->ib_dev);
return -ENOMEM;
ret = -ENOMEM;
goto fail_port;
}
ibdev->is_rep = true;
......@@ -58,12 +59,24 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
ibdev->mdev = dev;
ibdev->num_ports = num_ports;
if (!__mlx5_ib_add(ibdev, profile))
return -EINVAL;
ret = __mlx5_ib_add(ibdev, profile);
if (ret)
goto fail_add;
rep->rep_data[REP_IB].priv = ibdev;
return 0;
fail_add:
kfree(ibdev->port);
fail_port:
ib_dealloc_device(&ibdev->ib_dev);
return ret;
}
static void *mlx5_ib_rep_to_dev(struct mlx5_eswitch_rep *rep)
{
return rep->rep_data[REP_IB].priv;
}
static void
......@@ -83,59 +96,18 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
__mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
}
static void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep)
{
return mlx5_ib_rep_to_dev(rep);
}
static const struct mlx5_eswitch_rep_ops rep_ops = {
.load = mlx5_ib_vport_rep_load,
.unload = mlx5_ib_vport_rep_unload,
.get_proto_dev = mlx5_ib_vport_get_proto_dev,
.get_proto_dev = mlx5_ib_rep_to_dev,
};
void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB);
}
void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
mlx5_eswitch_unregister_vport_reps(esw, REP_IB);
}
u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw)
{
return mlx5_eswitch_mode(esw);
}
struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
u16 vport_num)
{
return mlx5_eswitch_get_proto_dev(esw, vport_num, REP_IB);
}
struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
u16 vport_num)
{
return mlx5_eswitch_get_proto_dev(esw, vport_num, REP_ETH);
}
struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw)
{
return mlx5_eswitch_uplink_get_proto_dev(esw, REP_IB);
}
struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
u16 vport_num)
{
return mlx5_eswitch_vport_rep(esw, vport_num);
}
struct mlx5_flow_handle *create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
struct mlx5_ib_sq *sq,
u16 port)
......@@ -154,3 +126,49 @@ struct mlx5_flow_handle *create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
return mlx5_eswitch_add_send_to_vport_rule(esw, rep->vport,
sq->base.mqp.qpn);
}
static int mlx5r_rep_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct mlx5_adev *idev = container_of(adev, struct mlx5_adev, adev);
struct mlx5_core_dev *mdev = idev->mdev;
struct mlx5_eswitch *esw;
esw = mdev->priv.eswitch;
mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB);
return 0;
}
static void mlx5r_rep_remove(struct auxiliary_device *adev)
{
struct mlx5_adev *idev = container_of(adev, struct mlx5_adev, adev);
struct mlx5_core_dev *mdev = idev->mdev;
struct mlx5_eswitch *esw;
esw = mdev->priv.eswitch;
mlx5_eswitch_unregister_vport_reps(esw, REP_IB);
}
static const struct auxiliary_device_id mlx5r_rep_id_table[] = {
{ .name = MLX5_ADEV_NAME ".rdma-rep", },
{},
};
MODULE_DEVICE_TABLE(auxiliary, mlx5r_rep_id_table);
static struct auxiliary_driver mlx5r_rep_driver = {
.name = "rep",
.probe = mlx5r_rep_probe,
.remove = mlx5r_rep_remove,
.id_table = mlx5r_rep_id_table,
};
int mlx5r_rep_init(void)
{
return auxiliary_driver_register(&mlx5r_rep_driver);
}
void mlx5r_rep_cleanup(void)
{
auxiliary_driver_unregister(&mlx5r_rep_driver);
}
......@@ -12,47 +12,16 @@
extern const struct mlx5_ib_profile raw_eth_profile;
#ifdef CONFIG_MLX5_ESWITCH
u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw);
struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
u16 vport_num);
struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw);
struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
u16 vport_num);
void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev);
void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev);
int mlx5r_rep_init(void);
void mlx5r_rep_cleanup(void);
struct mlx5_flow_handle *create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
struct mlx5_ib_sq *sq,
u16 port);
struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
u16 vport_num);
#else /* CONFIG_MLX5_ESWITCH */
static inline u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw)
{
return MLX5_ESWITCH_NONE;
}
static inline
struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
u16 vport_num)
{
return NULL;
}
static inline
struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw)
{
return NULL;
}
static inline
struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
u16 vport_num)
{
return NULL;
}
static inline void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev) {}
static inline void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev) {}
static inline int mlx5r_rep_init(void) { return 0; }
static inline void mlx5r_rep_cleanup(void) {}
static inline
struct mlx5_flow_handle *create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
struct mlx5_ib_sq *sq,
......@@ -68,10 +37,4 @@ struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
return NULL;
}
#endif
static inline
struct mlx5_ib_dev *mlx5_ib_rep_to_dev(struct mlx5_eswitch_rep *rep)
{
return rep->rep_data[REP_IB].priv;
}
#endif /* __MLX5_IB_REP_H__ */
......@@ -4593,7 +4593,7 @@ void __mlx5_ib_remove(struct mlx5_ib_dev *dev,
ib_dealloc_device(&dev->ib_dev);
}
void *__mlx5_ib_add(struct mlx5_ib_dev *dev,
int __mlx5_ib_add(struct mlx5_ib_dev *dev,
const struct mlx5_ib_profile *profile)
{
int err;
......@@ -4610,13 +4610,16 @@ void *__mlx5_ib_add(struct mlx5_ib_dev *dev,
}
dev->ib_active = true;
return dev;
return 0;
err_out:
__mlx5_ib_remove(dev, profile, i);
return NULL;
/* Clean up stages which were initialized */
while (i) {
i--;
if (profile->stage[i].cleanup)
profile->stage[i].cleanup(dev);
}
return -ENOMEM;
}
static const struct mlx5_ib_profile pf_profile = {
......@@ -4739,8 +4742,11 @@ const struct mlx5_ib_profile raw_eth_profile = {
NULL),
};
static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev)
static int mlx5r_mp_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct mlx5_adev *idev = container_of(adev, struct mlx5_adev, adev);
struct mlx5_core_dev *mdev = idev->mdev;
struct mlx5_ib_multiport_info *mpi;
struct mlx5_ib_dev *dev;
bool bound = false;
......@@ -4748,15 +4754,14 @@ static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev)
mpi = kzalloc(sizeof(*mpi), GFP_KERNEL);
if (!mpi)
return NULL;
return -ENOMEM;
mpi->mdev = mdev;
err = mlx5_query_nic_vport_system_image_guid(mdev,
&mpi->sys_image_guid);
if (err) {
kfree(mpi);
return NULL;
return err;
}
mutex_lock(&mlx5_ib_multiport_mutex);
......@@ -4777,40 +4782,46 @@ static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev)
}
mutex_unlock(&mlx5_ib_multiport_mutex);
return mpi;
dev_set_drvdata(&adev->dev, mpi);
return 0;
}
static void mlx5r_mp_remove(struct auxiliary_device *adev)
{
struct mlx5_ib_multiport_info *mpi;
mpi = dev_get_drvdata(&adev->dev);
mutex_lock(&mlx5_ib_multiport_mutex);
if (mpi->ibdev)
mlx5_ib_unbind_slave_port(mpi->ibdev, mpi);
list_del(&mpi->list);
mutex_unlock(&mlx5_ib_multiport_mutex);
kfree(mpi);
}
static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
static int mlx5r_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct mlx5_adev *idev = container_of(adev, struct mlx5_adev, adev);
struct mlx5_core_dev *mdev = idev->mdev;
const struct mlx5_ib_profile *profile;
int port_type_cap, num_ports, ret;
enum rdma_link_layer ll;
struct mlx5_ib_dev *dev;
int port_type_cap;
int num_ports;
if (MLX5_ESWITCH_MANAGER(mdev) &&
mlx5_ib_eswitch_mode(mdev->priv.eswitch) == MLX5_ESWITCH_OFFLOADS) {
if (!mlx5_core_mp_enabled(mdev))
mlx5_ib_register_vport_reps(mdev);
return mdev;
}
port_type_cap = MLX5_CAP_GEN(mdev, port_type);
ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
if (mlx5_core_is_mp_slave(mdev) && ll == IB_LINK_LAYER_ETHERNET)
return mlx5_ib_add_slave_port(mdev);
num_ports = max(MLX5_CAP_GEN(mdev, num_ports),
MLX5_CAP_GEN(mdev, num_vhca_ports));
dev = ib_alloc_device(mlx5_ib_dev, ib_dev);
if (!dev)
return NULL;
return -ENOMEM;
dev->port = kcalloc(num_ports, sizeof(*dev->port),
GFP_KERNEL);
if (!dev->port) {
ib_dealloc_device(&dev->ib_dev);
return NULL;
return -ENOMEM;
}
dev->mdev = mdev;
......@@ -4821,38 +4832,50 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
else
profile = &pf_profile;
return __mlx5_ib_add(dev, profile);
ret = __mlx5_ib_add(dev, profile);
if (ret) {
kfree(dev->port);
ib_dealloc_device(&dev->ib_dev);
return ret;
}
dev_set_drvdata(&adev->dev, dev);
return 0;
}
static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
static void mlx5r_remove(struct auxiliary_device *adev)
{
struct mlx5_ib_multiport_info *mpi;
struct mlx5_ib_dev *dev;
if (MLX5_ESWITCH_MANAGER(mdev) && context == mdev) {
mlx5_ib_unregister_vport_reps(mdev);
return;
}
if (mlx5_core_is_mp_slave(mdev)) {
mpi = context;
mutex_lock(&mlx5_ib_multiport_mutex);
if (mpi->ibdev)
mlx5_ib_unbind_slave_port(mpi->ibdev, mpi);
list_del(&mpi->list);
mutex_unlock(&mlx5_ib_multiport_mutex);
kfree(mpi);
return;
}
dev = context;
dev = dev_get_drvdata(&adev->dev);
__mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
}
static struct mlx5_interface mlx5_ib_interface = {
.add = mlx5_ib_add,
.remove = mlx5_ib_remove,
.protocol = MLX5_INTERFACE_PROTOCOL_IB,
static const struct auxiliary_device_id mlx5r_mp_id_table[] = {
{ .name = MLX5_ADEV_NAME ".multiport", },
{},
};
static const struct auxiliary_device_id mlx5r_id_table[] = {
{ .name = MLX5_ADEV_NAME ".rdma", },
{},
};
MODULE_DEVICE_TABLE(auxiliary, mlx5r_mp_id_table);
MODULE_DEVICE_TABLE(auxiliary, mlx5r_id_table);
static struct auxiliary_driver mlx5r_mp_driver = {
.name = "multiport",
.probe = mlx5r_mp_probe,
.remove = mlx5r_mp_remove,
.id_table = mlx5r_mp_id_table,
};
static struct auxiliary_driver mlx5r_driver = {
.name = "rdma",
.probe = mlx5r_probe,
.remove = mlx5r_remove,
.id_table = mlx5r_id_table,
};
unsigned long mlx5_ib_get_xlt_emergency_page(void)
......@@ -4868,7 +4891,7 @@ void mlx5_ib_put_xlt_emergency_page(void)
static int __init mlx5_ib_init(void)
{
int err;
int ret;
xlt_emergency_page = __get_free_page(GFP_KERNEL);
if (!xlt_emergency_page)
......@@ -4883,15 +4906,33 @@ static int __init mlx5_ib_init(void)
}
mlx5_ib_odp_init();
ret = mlx5r_rep_init();
if (ret)
goto rep_err;
ret = auxiliary_driver_register(&mlx5r_mp_driver);
if (ret)
goto mp_err;
ret = auxiliary_driver_register(&mlx5r_driver);
if (ret)
goto drv_err;
return 0;
err = mlx5_register_interface(&mlx5_ib_interface);
return err;
drv_err:
auxiliary_driver_unregister(&mlx5r_mp_driver);
mp_err:
mlx5r_rep_cleanup();
rep_err:
destroy_workqueue(mlx5_ib_event_wq);
free_page((unsigned long)xlt_emergency_page);
return ret;
}
static void __exit mlx5_ib_cleanup(void)
{
mlx5_unregister_interface(&mlx5_ib_interface);
auxiliary_driver_unregister(&mlx5r_driver);
auxiliary_driver_unregister(&mlx5r_mp_driver);
mlx5r_rep_cleanup();
destroy_workqueue(mlx5_ib_event_wq);
mutex_destroy(&xlt_emergency_page_mutex);
free_page(xlt_emergency_page);
......
......@@ -1317,7 +1317,7 @@ extern const struct mmu_interval_notifier_ops mlx5_mn_ops;
void __mlx5_ib_remove(struct mlx5_ib_dev *dev,
const struct mlx5_ib_profile *profile,
int stage);
void *__mlx5_ib_add(struct mlx5_ib_dev *dev,
int __mlx5_ib_add(struct mlx5_ib_dev *dev,
const struct mlx5_ib_profile *profile);
int mlx5_ib_get_vf_config(struct ib_device *device, int vf,
......
......@@ -6,6 +6,7 @@
config MLX5_CORE
tristate "Mellanox 5th generation network adapters (ConnectX series) core driver"
depends on PCI
select AUXILIARY_BUS
select NET_DEVLINK
depends on VXLAN || !VXLAN
depends on MLXFW || !MLXFW
......
......@@ -43,7 +43,7 @@ mlx5_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
u32 running_fw, stored_fw;
int err;
err = devlink_info_driver_name_put(req, DRIVER_NAME);
err = devlink_info_driver_name_put(req, KBUILD_MODNAME);
if (err)
return err;
......@@ -212,7 +212,7 @@ static int mlx5_devlink_fs_mode_validate(struct devlink *devlink, u32 id,
u8 eswitch_mode;
bool smfs_cap;
eswitch_mode = mlx5_eswitch_mode(dev->priv.eswitch);
eswitch_mode = mlx5_eswitch_mode(dev);
smfs_cap = mlx5_fs_dr_is_supported(dev);
if (!smfs_cap) {
......
......@@ -41,9 +41,7 @@ void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv,
{
struct mlx5_core_dev *mdev = priv->mdev;
strlcpy(drvinfo->driver, DRIVER_NAME, sizeof(drvinfo->driver));
strlcpy(drvinfo->version, DRIVER_VERSION,
sizeof(drvinfo->version));
strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
"%d.%d.%04d (%.16s)",
fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev),
......
......@@ -3112,7 +3112,7 @@ static void mlx5e_modify_admin_state(struct mlx5_core_dev *mdev,
mlx5_set_port_admin_status(mdev, state);
if (!MLX5_ESWITCH_MANAGER(mdev) || mlx5_eswitch_mode(esw) == MLX5_ESWITCH_OFFLOADS)
if (mlx5_eswitch_mode(mdev) != MLX5_ESWITCH_LEGACY)
return;
if (state == MLX5_PORT_UP)
......@@ -4577,31 +4577,6 @@ const struct net_device_ops mlx5e_netdev_ops = {
.ndo_get_devlink_port = mlx5e_get_devlink_port,
};
static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
{
if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
return -EOPNOTSUPP;
if (!MLX5_CAP_GEN(mdev, eth_net_offloads) ||
!MLX5_CAP_GEN(mdev, nic_flow_table) ||
!MLX5_CAP_ETH(mdev, csum_cap) ||
!MLX5_CAP_ETH(mdev, max_lso_cap) ||
!MLX5_CAP_ETH(mdev, vlan_cap) ||
!MLX5_CAP_ETH(mdev, rss_ind_tbl_cap) ||
MLX5_CAP_FLOWTABLE(mdev,
flow_table_properties_nic_receive.max_ft_level)
< 3) {
mlx5_core_warn(mdev,
"Not creating net device, some required device capabilities are missing\n");
return -EOPNOTSUPP;
}
if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
if (!MLX5_CAP_GEN(mdev, cq_moderation))
mlx5_core_warn(mdev, "CQ moderation is not supported\n");
return 0;
}
void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
int num_channels)
{
......@@ -5421,13 +5396,12 @@ void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
free_netdev(netdev);
}
/* mlx5e_attach and mlx5e_detach scope should be only creating/destroying
* hardware contexts and to connect it to the current netdev.
*/
static int mlx5e_attach(struct mlx5_core_dev *mdev, void *vpriv)
static int mlx5e_resume(struct auxiliary_device *adev)
{
struct mlx5e_priv *priv = vpriv;
struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
struct mlx5e_priv *priv = dev_get_drvdata(&adev->dev);
struct net_device *netdev = priv->netdev;
struct mlx5_core_dev *mdev = edev->mdev;
int err;
if (netif_device_present(netdev))
......@@ -5446,109 +5420,111 @@ static int mlx5e_attach(struct mlx5_core_dev *mdev, void *vpriv)
return 0;
}
static void mlx5e_detach(struct mlx5_core_dev *mdev, void *vpriv)
static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state)
{
struct mlx5e_priv *priv = vpriv;
struct mlx5e_priv *priv = dev_get_drvdata(&adev->dev);
struct net_device *netdev = priv->netdev;
#ifdef CONFIG_MLX5_ESWITCH
if (MLX5_ESWITCH_MANAGER(mdev) && vpriv == mdev)
return;
#endif
struct mlx5_core_dev *mdev = priv->mdev;
if (!netif_device_present(netdev))
return;
return -ENODEV;
mlx5e_detach_netdev(priv);
mlx5e_destroy_mdev_resources(mdev);
return 0;
}
static void *mlx5e_add(struct mlx5_core_dev *mdev)
static int mlx5e_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
struct mlx5_core_dev *mdev = edev->mdev;
struct net_device *netdev;
pm_message_t state = {};
void *priv;
int err;
int nch;
err = mlx5e_check_required_hca_cap(mdev);
if (err)
return NULL;
#ifdef CONFIG_MLX5_ESWITCH
if (MLX5_ESWITCH_MANAGER(mdev) &&
mlx5_eswitch_mode(mdev->priv.eswitch) == MLX5_ESWITCH_OFFLOADS) {
mlx5e_rep_register_vport_reps(mdev);
return mdev;
}
#endif
nch = mlx5e_get_max_num_channels(mdev);
netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, nch, NULL);
if (!netdev) {
mlx5_core_err(mdev, "mlx5e_create_netdev failed\n");
return NULL;
return -ENOMEM;
}
dev_net_set(netdev, mlx5_core_net(mdev));
priv = netdev_priv(netdev);
dev_set_drvdata(&adev->dev, priv);
err = mlx5e_attach(mdev, priv);
err = mlx5e_resume(adev);
if (err) {
mlx5_core_err(mdev, "mlx5e_attach failed, %d\n", err);
mlx5_core_err(mdev, "mlx5e_resume failed, %d\n", err);
goto err_destroy_netdev;
}
err = register_netdev(netdev);
if (err) {
mlx5_core_err(mdev, "register_netdev failed, %d\n", err);
goto err_detach;
goto err_resume;
}
mlx5e_devlink_port_type_eth_set(priv);
mlx5e_dcbnl_init_app(priv);
return priv;
return 0;
err_detach:
mlx5e_detach(mdev, priv);
err_resume:
mlx5e_suspend(adev, state);
err_destroy_netdev:
mlx5e_destroy_netdev(priv);
return NULL;
return err;
}
static void mlx5e_remove(struct mlx5_core_dev *mdev, void *vpriv)
static void mlx5e_remove(struct auxiliary_device *adev)
{
struct mlx5e_priv *priv;
struct mlx5e_priv *priv = dev_get_drvdata(&adev->dev);
pm_message_t state = {};
#ifdef CONFIG_MLX5_ESWITCH
if (MLX5_ESWITCH_MANAGER(mdev) && vpriv == mdev) {
mlx5e_rep_unregister_vport_reps(mdev);
return;
}
#endif
priv = vpriv;
mlx5e_dcbnl_delete_app(priv);
unregister_netdev(priv->netdev);
mlx5e_detach(mdev, vpriv);
mlx5e_suspend(adev, state);
mlx5e_destroy_netdev(priv);
}
static struct mlx5_interface mlx5e_interface = {
.add = mlx5e_add,
static const struct auxiliary_device_id mlx5e_id_table[] = {
{ .name = MLX5_ADEV_NAME ".eth", },
{},
};
MODULE_DEVICE_TABLE(auxiliary, mlx5e_id_table);
static struct auxiliary_driver mlx5e_driver = {
.name = "eth",
.probe = mlx5e_probe,
.remove = mlx5e_remove,
.attach = mlx5e_attach,
.detach = mlx5e_detach,
.protocol = MLX5_INTERFACE_PROTOCOL_ETH,
.suspend = mlx5e_suspend,
.resume = mlx5e_resume,
.id_table = mlx5e_id_table,
};
void mlx5e_init(void)
int mlx5e_init(void)
{
int ret;
mlx5e_ipsec_build_inverse_table();
mlx5e_build_ptys2ethtool_map();
mlx5_register_interface(&mlx5e_interface);
ret = mlx5e_rep_init();
if (ret)
return ret;
ret = auxiliary_driver_register(&mlx5e_driver);
if (ret)
mlx5e_rep_cleanup();
return ret;
}
void mlx5e_cleanup(void)
{
mlx5_unregister_interface(&mlx5e_interface);
auxiliary_driver_unregister(&mlx5e_driver);
mlx5e_rep_cleanup();
}
......@@ -64,7 +64,6 @@ static void mlx5e_rep_get_drvinfo(struct net_device *dev,
strlcpy(drvinfo->driver, mlx5e_rep_driver_name,
sizeof(drvinfo->driver));
strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
"%d.%d.%04d (%.16s)",
fw_rev_maj(mdev), fw_rev_min(mdev),
......@@ -1316,16 +1315,48 @@ static const struct mlx5_eswitch_rep_ops rep_ops = {
.get_proto_dev = mlx5e_vport_rep_get_proto_dev
};
void mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev)
static int mlx5e_rep_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
struct mlx5_core_dev *mdev = edev->mdev;
struct mlx5_eswitch *esw;
esw = mdev->priv.eswitch;
mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_ETH);
return 0;
}
void mlx5e_rep_unregister_vport_reps(struct mlx5_core_dev *mdev)
static void mlx5e_rep_remove(struct auxiliary_device *adev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
struct mlx5_adev *vdev = container_of(adev, struct mlx5_adev, adev);
struct mlx5_core_dev *mdev = vdev->mdev;
struct mlx5_eswitch *esw;
esw = mdev->priv.eswitch;
mlx5_eswitch_unregister_vport_reps(esw, REP_ETH);
}
static const struct auxiliary_device_id mlx5e_rep_id_table[] = {
{ .name = MLX5_ADEV_NAME ".eth-rep", },
{},
};
MODULE_DEVICE_TABLE(auxiliary, mlx5e_rep_id_table);
static struct auxiliary_driver mlx5e_rep_driver = {
.name = "eth-rep",
.probe = mlx5e_rep_probe,
.remove = mlx5e_rep_remove,
.id_table = mlx5e_rep_id_table,
};
int mlx5e_rep_init(void)
{
return auxiliary_driver_register(&mlx5e_rep_driver);
}
void mlx5e_rep_cleanup(void)
{
auxiliary_driver_unregister(&mlx5e_rep_driver);
}
......@@ -203,8 +203,8 @@ struct mlx5e_rep_sq {
struct list_head list;
};
void mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev);
void mlx5e_rep_unregister_vport_reps(struct mlx5_core_dev *mdev);
int mlx5e_rep_init(void);
void mlx5e_rep_cleanup(void);
int mlx5e_rep_bond_init(struct mlx5e_rep_priv *rpriv);
void mlx5e_rep_bond_cleanup(struct mlx5e_rep_priv *rpriv);
int mlx5e_rep_bond_enslave(struct mlx5_eswitch *esw, struct net_device *netdev,
......@@ -232,6 +232,8 @@ static inline bool mlx5e_eswitch_rep(struct net_device *netdev)
static inline bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) { return false; }
static inline int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv) { return 0; }
static inline void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv) {}
static inline int mlx5e_rep_init(void) { return 0; };
static inline void mlx5e_rep_cleanup(void) {};
#endif
static inline bool mlx5e_is_vport_rep(struct mlx5e_priv *priv)
......
......@@ -271,8 +271,6 @@ mlx5e_tc_match_to_reg_set(struct mlx5_core_dev *mdev,
return 0;
}
#define esw_offloads_mode(esw) (mlx5_eswitch_mode(esw) == MLX5_ESWITCH_OFFLOADS)
static struct mlx5_tc_ct_priv *
get_ct_priv(struct mlx5e_priv *priv)
{
......@@ -280,7 +278,7 @@ get_ct_priv(struct mlx5e_priv *priv)
struct mlx5_rep_uplink_priv *uplink_priv;
struct mlx5e_rep_priv *uplink_rpriv;
if (esw_offloads_mode(esw)) {
if (is_mdev_switchdev_mode(priv->mdev)) {
uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
uplink_priv = &uplink_rpriv->uplink_priv;
......@@ -297,7 +295,7 @@ mlx5_tc_rule_insert(struct mlx5e_priv *priv,
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
if (esw_offloads_mode(esw))
if (is_mdev_switchdev_mode(priv->mdev))
return mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
return mlx5e_add_offloaded_nic_rule(priv, spec, attr);
......@@ -310,7 +308,7 @@ mlx5_tc_rule_delete(struct mlx5e_priv *priv,
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
if (esw_offloads_mode(esw)) {
if (is_mdev_switchdev_mode(priv->mdev)) {
mlx5_eswitch_del_offloaded_rule(esw, rule, attr);
return;
......
......@@ -1641,8 +1641,7 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int mode, int num_vfs)
if (mode == MLX5_ESWITCH_LEGACY) {
err = esw_legacy_enable(esw);
} else {
mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
mlx5_rescan_drivers(esw->dev);
err = esw_offloads_enable(esw);
}
......@@ -1660,10 +1659,9 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int mode, int num_vfs)
abort:
esw->mode = MLX5_ESWITCH_NONE;
if (mode == MLX5_ESWITCH_OFFLOADS) {
mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
}
if (mode == MLX5_ESWITCH_OFFLOADS)
mlx5_rescan_drivers(esw->dev);
esw_destroy_tsar(esw);
return err;
}
......@@ -1724,10 +1722,9 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf)
mlx5_lag_update(esw->dev);
if (old_mode == MLX5_ESWITCH_OFFLOADS) {
mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
}
if (old_mode == MLX5_ESWITCH_OFFLOADS)
mlx5_rescan_drivers(esw->dev);
esw_destroy_tsar(esw);
if (clear_vf)
......@@ -2466,8 +2463,10 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
return err;
}
u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw)
u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev)
{
struct mlx5_eswitch *esw = dev->priv.eswitch;
return ESW_ALLOWED(esw) ? esw->mode : MLX5_ESWITCH_NONE;
}
EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
......
......@@ -39,7 +39,7 @@ static void mlx5i_get_drvinfo(struct net_device *dev,
struct mlx5e_priv *priv = mlx5i_epriv(dev);
mlx5e_ethtool_get_drvinfo(priv, drvinfo);
strlcpy(drvinfo->driver, DRIVER_NAME "[ib_ipoib]",
strlcpy(drvinfo->driver, KBUILD_MODNAME "[ib_ipoib]",
sizeof(drvinfo->driver));
}
......
......@@ -243,24 +243,30 @@ static bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
#endif
}
static void mlx5_lag_add_ib_devices(struct mlx5_lag *ldev)
static void mlx5_lag_add_devices(struct mlx5_lag *ldev)
{
int i;
for (i = 0; i < MLX5_MAX_PORTS; i++)
if (ldev->pf[i].dev)
mlx5_add_dev_by_protocol(ldev->pf[i].dev,
MLX5_INTERFACE_PROTOCOL_IB);
for (i = 0; i < MLX5_MAX_PORTS; i++) {
if (!ldev->pf[i].dev)
continue;
ldev->pf[i].dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(ldev->pf[i].dev);
}
}
static void mlx5_lag_remove_ib_devices(struct mlx5_lag *ldev)
static void mlx5_lag_remove_devices(struct mlx5_lag *ldev)
{
int i;
for (i = 0; i < MLX5_MAX_PORTS; i++)
if (ldev->pf[i].dev)
mlx5_remove_dev_by_protocol(ldev->pf[i].dev,
MLX5_INTERFACE_PROTOCOL_IB);
for (i = 0; i < MLX5_MAX_PORTS; i++) {
if (!ldev->pf[i].dev)
continue;
ldev->pf[i].dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(ldev->pf[i].dev);
}
}
static void mlx5_do_bond(struct mlx5_lag *ldev)
......@@ -290,20 +296,21 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
#endif
if (roce_lag)
mlx5_lag_remove_ib_devices(ldev);
mlx5_lag_remove_devices(ldev);
err = mlx5_activate_lag(ldev, &tracker,
roce_lag ? MLX5_LAG_FLAG_ROCE :
MLX5_LAG_FLAG_SRIOV);
if (err) {
if (roce_lag)
mlx5_lag_add_ib_devices(ldev);
mlx5_lag_add_devices(ldev);
return;
}
if (roce_lag) {
mlx5_add_dev_by_protocol(dev0, MLX5_INTERFACE_PROTOCOL_IB);
dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
mlx5_nic_vport_enable_roce(dev1);
}
} else if (do_bond && __mlx5_lag_is_active(ldev)) {
......@@ -312,7 +319,8 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
roce_lag = __mlx5_lag_is_roce(ldev);
if (roce_lag) {
mlx5_remove_dev_by_protocol(dev0, MLX5_INTERFACE_PROTOCOL_IB);
dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
mlx5_nic_vport_disable_roce(dev1);
}
......@@ -321,7 +329,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
return;
if (roce_lag)
mlx5_lag_add_ib_devices(ldev);
mlx5_lag_add_devices(ldev);
}
}
......@@ -596,6 +604,8 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
if (err)
mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",
err);
return;
}
/* Must be called with intf_mutex held */
......@@ -739,24 +749,6 @@ u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev,
}
EXPORT_SYMBOL(mlx5_lag_get_slave_port);
bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv)
{
struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev,
priv);
struct mlx5_lag *ldev;
if (intf->protocol != MLX5_INTERFACE_PROTOCOL_IB)
return true;
ldev = mlx5_lag_dev_get(dev);
if (!ldev || !__mlx5_lag_is_roce(ldev) ||
ldev->pf[MLX5_LAG_P1].dev == dev)
return true;
/* If bonded, we do not add an IB device for PF1. */
return false;
}
int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
u64 *values,
int num_counters,
......
......@@ -50,6 +50,7 @@
#ifdef CONFIG_RFS_ACCEL
#include <linux/cpu_rmap.h>
#endif
#include <linux/version.h>
#include <net/devlink.h>
#include "mlx5_core.h"
#include "lib/eq.h"
......@@ -76,7 +77,6 @@
MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRIVER_VERSION);
unsigned int mlx5_core_debug_mask;
module_param_named(debug_mask, mlx5_core_debug_mask, uint, 0644);
......@@ -227,13 +227,16 @@ static void mlx5_set_driver_version(struct mlx5_core_dev *dev)
strncat(string, ",", remaining_size);
remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
strncat(string, DRIVER_NAME, remaining_size);
strncat(string, KBUILD_MODNAME, remaining_size);
remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
strncat(string, ",", remaining_size);
remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
strncat(string, DRIVER_VERSION, remaining_size);
snprintf(string + strlen(string), remaining_size, "%u.%u.%u",
(u8)((LINUX_VERSION_CODE >> 16) & 0xff), (u8)((LINUX_VERSION_CODE >> 8) & 0xff),
(u16)(LINUX_VERSION_CODE & 0xffff));
/*Send the command*/
MLX5_SET(set_driver_version_in, in, opcode,
......@@ -309,7 +312,7 @@ static int request_bar(struct pci_dev *pdev)
return -ENODEV;
}
err = pci_request_regions(pdev, DRIVER_NAME);
err = pci_request_regions(pdev, KBUILD_MODNAME);
if (err)
dev_err(&pdev->dev, "Couldn't get PCI resources, aborting\n");
......@@ -1219,14 +1222,21 @@ int mlx5_load_one(struct mlx5_core_dev *dev, bool boot)
err = mlx5_devlink_register(priv_to_devlink(dev), dev->device);
if (err)
goto err_devlink_reg;
mlx5_register_device(dev);
err = mlx5_register_device(dev);
} else {
mlx5_attach_device(dev);
err = mlx5_attach_device(dev);
}
if (err)
goto err_register;
mutex_unlock(&dev->intf_state_mutex);
return 0;
err_register:
if (boot)
mlx5_devlink_unregister(priv_to_devlink(dev));
err_devlink_reg:
clear_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state);
mlx5_unload(dev);
......@@ -1303,8 +1313,14 @@ static int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx)
if (err)
goto err_pagealloc_init;
err = mlx5_adev_init(dev);
if (err)
goto err_adev_init;
return 0;
err_adev_init:
mlx5_pagealloc_cleanup(dev);
err_pagealloc_init:
mlx5_health_cleanup(dev);
err_health_init:
......@@ -1321,6 +1337,7 @@ static void mlx5_mdev_uninit(struct mlx5_core_dev *dev)
{
struct mlx5_priv *priv = &dev->priv;
mlx5_adev_cleanup(dev);
mlx5_pagealloc_cleanup(dev);
mlx5_health_cleanup(dev);
debugfs_remove_recursive(dev->priv.dbg_root);
......@@ -1331,7 +1348,6 @@ static void mlx5_mdev_uninit(struct mlx5_core_dev *dev)
mutex_destroy(&dev->intf_state_mutex);
}
#define MLX5_IB_MOD "mlx5_ib"
static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct mlx5_core_dev *dev;
......@@ -1351,6 +1367,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
dev->coredev_type = id->driver_data & MLX5_PCI_DEV_IS_VF ?
MLX5_COREDEV_VF : MLX5_COREDEV_PF;
dev->priv.adev_idx = mlx5_adev_idx_alloc();
if (dev->priv.adev_idx < 0)
return dev->priv.adev_idx;
err = mlx5_mdev_init(dev, prof_sel);
if (err)
goto mdev_init_err;
......@@ -1369,8 +1389,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_load_one;
}
request_module_nowait(MLX5_IB_MOD);
err = mlx5_crdump_enable(dev);
if (err)
dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err);
......@@ -1384,6 +1402,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_init_err:
mlx5_mdev_uninit(dev);
mdev_init_err:
mlx5_adev_idx_free(dev->priv.adev_idx);
mlx5_devlink_free(devlink);
return err;
......@@ -1400,6 +1419,7 @@ static void remove_one(struct pci_dev *pdev)
mlx5_unload_one(dev, true);
mlx5_pci_close(dev);
mlx5_mdev_uninit(dev);
mlx5_adev_idx_free(dev->priv.adev_idx);
mlx5_devlink_free(devlink);
}
......@@ -1614,7 +1634,7 @@ void mlx5_recover_device(struct mlx5_core_dev *dev)
}
static struct pci_driver mlx5_core_driver = {
.name = DRIVER_NAME,
.name = KBUILD_MODNAME,
.id_table = mlx5_core_pci_table,
.probe = init_one,
.remove = remove_one,
......@@ -1640,6 +1660,9 @@ static int __init init(void)
{
int err;
WARN_ONCE(strcmp(MLX5_ADEV_NAME, KBUILD_MODNAME),
"mlx5_core name not in sync with kernel module name");
get_random_bytes(&sw_owner_id, sizeof(sw_owner_id));
mlx5_core_verify_params();
......@@ -1651,7 +1674,11 @@ static int __init init(void)
goto err_debug;
#ifdef CONFIG_MLX5_CORE_EN
mlx5e_init();
err = mlx5e_init();
if (err) {
pci_unregister_driver(&mlx5_core_driver);
goto err_debug;
}
#endif
return 0;
......
......@@ -42,9 +42,6 @@
#include <linux/mlx5/fs.h>
#include <linux/mlx5/driver.h>
#define DRIVER_NAME "mlx5_core"
#define DRIVER_VERSION "5.0-0"
extern uint mlx5_core_debug_mask;
#define mlx5_core_dbg(__dev, format, ...) \
......@@ -185,22 +182,20 @@ void mlx5_events_cleanup(struct mlx5_core_dev *dev);
void mlx5_events_start(struct mlx5_core_dev *dev);
void mlx5_events_stop(struct mlx5_core_dev *dev);
void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv);
void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv);
void mlx5_attach_device(struct mlx5_core_dev *dev);
int mlx5_adev_idx_alloc(void);
void mlx5_adev_idx_free(int idx);
void mlx5_adev_cleanup(struct mlx5_core_dev *dev);
int mlx5_adev_init(struct mlx5_core_dev *dev);
int mlx5_attach_device(struct mlx5_core_dev *dev);
void mlx5_detach_device(struct mlx5_core_dev *dev);
bool mlx5_device_registered(struct mlx5_core_dev *dev);
void mlx5_register_device(struct mlx5_core_dev *dev);
int mlx5_register_device(struct mlx5_core_dev *dev);
void mlx5_unregister_device(struct mlx5_core_dev *dev);
void mlx5_add_dev_by_protocol(struct mlx5_core_dev *dev, int protocol);
void mlx5_remove_dev_by_protocol(struct mlx5_core_dev *dev, int protocol);
struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev);
void mlx5_dev_list_lock(void);
void mlx5_dev_list_unlock(void);
int mlx5_dev_list_trylock(void);
bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv);
int mlx5_query_mtpps(struct mlx5_core_dev *dev, u32 *mtpps, u32 mtpps_size);
int mlx5_set_mtpps(struct mlx5_core_dev *mdev, u32 *mtpps, u32 mtpps_size);
int mlx5_query_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 *arm, u8 *mode);
......@@ -219,7 +214,7 @@ int mlx5_firmware_flash(struct mlx5_core_dev *dev, const struct firmware *fw,
int mlx5_fw_version_query(struct mlx5_core_dev *dev,
u32 *running_ver, u32 *stored_ver);
void mlx5e_init(void);
int mlx5e_init(void);
void mlx5e_cleanup(void);
static inline bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev)
......@@ -239,7 +234,17 @@ static inline int mlx5_lag_is_lacp_owner(struct mlx5_core_dev *dev)
MLX5_CAP_GEN(dev, lag_master);
}
void mlx5_reload_interface(struct mlx5_core_dev *mdev, int protocol);
int mlx5_rescan_drivers_locked(struct mlx5_core_dev *dev);
static inline int mlx5_rescan_drivers(struct mlx5_core_dev *dev)
{
int ret;
mlx5_dev_list_lock();
ret = mlx5_rescan_drivers_locked(dev);
mlx5_dev_list_unlock();
return ret;
}
void mlx5_lag_update(struct mlx5_core_dev *dev);
enum {
......
subdir-ccflags-y += -I$(srctree)/drivers/vdpa/mlx5/core
obj-$(CONFIG_MLX5_VDPA_NET) += mlx5_vdpa.o
mlx5_vdpa-$(CONFIG_MLX5_VDPA_NET) += net/main.o net/mlx5_vnet.o core/resources.o core/mr.o
mlx5_vdpa-$(CONFIG_MLX5_VDPA_NET) += net/mlx5_vnet.o core/resources.o core/mr.o
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2020 Mellanox Technologies Ltd. */
#include <linux/module.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/device.h>
#include "mlx5_vdpa_ifc.h"
#include "mlx5_vnet.h"
MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
MODULE_DESCRIPTION("Mellanox VDPA driver");
MODULE_LICENSE("Dual BSD/GPL");
static bool required_caps_supported(struct mlx5_core_dev *mdev)
{
u8 event_mode;
u64 got;
got = MLX5_CAP_GEN_64(mdev, general_obj_types);
if (!(got & MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q))
return false;
event_mode = MLX5_CAP_DEV_VDPA_EMULATION(mdev, event_mode);
if (!(event_mode & MLX5_VIRTIO_Q_EVENT_MODE_QP_MODE))
return false;
if (!MLX5_CAP_DEV_VDPA_EMULATION(mdev, eth_frame_offload_type))
return false;
return true;
}
static void *mlx5_vdpa_add(struct mlx5_core_dev *mdev)
{
struct mlx5_vdpa_dev *vdev;
if (mlx5_core_is_pf(mdev))
return NULL;
if (!required_caps_supported(mdev)) {
dev_info(mdev->device, "virtio net emulation not supported\n");
return NULL;
}
vdev = mlx5_vdpa_add_dev(mdev);
if (IS_ERR(vdev))
return NULL;
return vdev;
}
static void mlx5_vdpa_remove(struct mlx5_core_dev *mdev, void *context)
{
struct mlx5_vdpa_dev *vdev = context;
mlx5_vdpa_remove_dev(vdev);
}
static struct mlx5_interface mlx5_vdpa_interface = {
.add = mlx5_vdpa_add,
.remove = mlx5_vdpa_remove,
.protocol = MLX5_INTERFACE_PROTOCOL_VDPA,
};
static int __init mlx5_vdpa_init(void)
{
return mlx5_register_interface(&mlx5_vdpa_interface);
}
static void __exit mlx5_vdpa_exit(void)
{
mlx5_unregister_interface(&mlx5_vdpa_interface);
}
module_init(mlx5_vdpa_init);
module_exit(mlx5_vdpa_exit);
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2020 Mellanox Technologies Ltd. */
#include <linux/module.h>
#include <linux/vdpa.h>
#include <linux/vringh.h>
#include <uapi/linux/virtio_net.h>
#include <uapi/linux/virtio_ids.h>
#include <linux/virtio_config.h>
#include <linux/auxiliary_bus.h>
#include <linux/mlx5/cq.h>
#include <linux/mlx5/qp.h>
#include <linux/mlx5/device.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/vport.h>
#include <linux/mlx5/fs.h>
#include <linux/mlx5/device.h>
#include "mlx5_vnet.h"
#include "mlx5_vdpa_ifc.h"
#include <linux/mlx5/mlx5_ifc_vdpa.h>
#include "mlx5_vdpa.h"
MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
MODULE_DESCRIPTION("Mellanox VDPA driver");
MODULE_LICENSE("Dual BSD/GPL");
#define to_mlx5_vdpa_ndev(__mvdev) \
container_of(__mvdev, struct mlx5_vdpa_net, mvdev)
#define to_mvdev(__vdev) container_of((__vdev), struct mlx5_vdpa_dev, vdev)
#define VALID_FEATURES_MASK \
......@@ -159,6 +169,11 @@ static bool mlx5_vdpa_debug;
mlx5_vdpa_info(mvdev, "%s\n", #_status); \
} while (0)
static inline u32 mlx5_vdpa_max_qps(int max_vqs)
{
return max_vqs / 2;
}
static void print_status(struct mlx5_vdpa_dev *mvdev, u8 status, bool set)
{
if (status & ~VALID_STATUS_MASK)
......@@ -1928,8 +1943,11 @@ static void init_mvqs(struct mlx5_vdpa_net *ndev)
}
}
void *mlx5_vdpa_add_dev(struct mlx5_core_dev *mdev)
static int mlx5v_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct mlx5_adev *madev = container_of(adev, struct mlx5_adev, adev);
struct mlx5_core_dev *mdev = madev->mdev;
struct virtio_net_config *config;
struct mlx5_vdpa_dev *mvdev;
struct mlx5_vdpa_net *ndev;
......@@ -1943,7 +1961,7 @@ void *mlx5_vdpa_add_dev(struct mlx5_core_dev *mdev)
ndev = vdpa_alloc_device(struct mlx5_vdpa_net, mvdev.vdev, mdev->device, &mlx5_vdpa_ops,
2 * mlx5_vdpa_max_qps(max_vqs));
if (IS_ERR(ndev))
return ndev;
return PTR_ERR(ndev);
ndev->mvdev.max_vqs = max_vqs;
mvdev = &ndev->mvdev;
......@@ -1972,7 +1990,8 @@ void *mlx5_vdpa_add_dev(struct mlx5_core_dev *mdev)
if (err)
goto err_reg;
return ndev;
dev_set_drvdata(&adev->dev, ndev);
return 0;
err_reg:
free_resources(ndev);
......@@ -1981,10 +2000,28 @@ void *mlx5_vdpa_add_dev(struct mlx5_core_dev *mdev)
err_mtu:
mutex_destroy(&ndev->reslock);
put_device(&mvdev->vdev.dev);
return ERR_PTR(err);
return err;
}
void mlx5_vdpa_remove_dev(struct mlx5_vdpa_dev *mvdev)
static void mlx5v_remove(struct auxiliary_device *adev)
{
struct mlx5_vdpa_dev *mvdev = dev_get_drvdata(&adev->dev);
vdpa_unregister_device(&mvdev->vdev);
}
static const struct auxiliary_device_id mlx5v_id_table[] = {
{ .name = MLX5_ADEV_NAME ".vnet", },
{},
};
MODULE_DEVICE_TABLE(auxiliary, mlx5v_id_table);
static struct auxiliary_driver mlx5v_driver = {
.name = "vnet",
.probe = mlx5v_probe,
.remove = mlx5v_remove,
.id_table = mlx5v_id_table,
};
module_auxiliary_driver(mlx5v_driver);
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2020 Mellanox Technologies Ltd. */
#ifndef __MLX5_VNET_H_
#define __MLX5_VNET_H_
#include <linux/vdpa.h>
#include <linux/virtio_net.h>
#include <linux/vringh.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/cq.h>
#include <linux/mlx5/qp.h>
#include "mlx5_vdpa.h"
static inline u32 mlx5_vdpa_max_qps(int max_vqs)
{
return max_vqs / 2;
}
#define to_mlx5_vdpa_ndev(__mvdev) container_of(__mvdev, struct mlx5_vdpa_net, mvdev)
void *mlx5_vdpa_add_dev(struct mlx5_core_dev *mdev);
void mlx5_vdpa_remove_dev(struct mlx5_vdpa_dev *mvdev);
#endif /* __MLX5_VNET_H_ */
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2020 Intel Corporation
*
* Please see Documentation/driver-api/auxiliary_bus.rst for more information.
*/
#ifndef _AUXILIARY_BUS_H_
#define _AUXILIARY_BUS_H_
#include <linux/device.h>
#include <linux/mod_devicetable.h>
struct auxiliary_device {
struct device dev;
const char *name;
u32 id;
};
struct auxiliary_driver {
int (*probe)(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id);
void (*remove)(struct auxiliary_device *auxdev);
void (*shutdown)(struct auxiliary_device *auxdev);
int (*suspend)(struct auxiliary_device *auxdev, pm_message_t state);
int (*resume)(struct auxiliary_device *auxdev);
const char *name;
struct device_driver driver;
const struct auxiliary_device_id *id_table;
};
static inline struct auxiliary_device *to_auxiliary_dev(struct device *dev)
{
return container_of(dev, struct auxiliary_device, dev);
}
static inline struct auxiliary_driver *to_auxiliary_drv(struct device_driver *drv)
{
return container_of(drv, struct auxiliary_driver, driver);
}
int auxiliary_device_init(struct auxiliary_device *auxdev);
int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname);
#define auxiliary_device_add(auxdev) __auxiliary_device_add(auxdev, KBUILD_MODNAME)
static inline void auxiliary_device_uninit(struct auxiliary_device *auxdev)
{
put_device(&auxdev->dev);
}
static inline void auxiliary_device_delete(struct auxiliary_device *auxdev)
{
device_del(&auxdev->dev);
}
int __auxiliary_driver_register(struct auxiliary_driver *auxdrv, struct module *owner,
const char *modname);
#define auxiliary_driver_register(auxdrv) \
__auxiliary_driver_register(auxdrv, THIS_MODULE, KBUILD_MODNAME)
void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv);
/**
* module_auxiliary_driver() - Helper macro for registering an auxiliary driver
* @__auxiliary_driver: auxiliary driver struct
*
* Helper macro for auxiliary drivers which do not do anything special in
* module init/exit. This eliminates a lot of boilerplate. Each module may only
* use this macro once, and calling it replaces module_init() and module_exit()
*/
#define module_auxiliary_driver(__auxiliary_driver) \
module_driver(__auxiliary_driver, auxiliary_driver_register, auxiliary_driver_unregister)
struct auxiliary_device *auxiliary_find_device(struct device *start,
const void *data,
int (*match)(struct device *dev, const void *data));
#endif /* _AUXILIARY_BUS_H_ */
......@@ -48,6 +48,7 @@
#include <linux/idr.h>
#include <linux/notifier.h>
#include <linux/refcount.h>
#include <linux/auxiliary_bus.h>
#include <linux/mlx5/device.h>
#include <linux/mlx5/doorbell.h>
......@@ -56,6 +57,8 @@
#include <linux/ptp_clock_kernel.h>
#include <net/devlink.h>
#define MLX5_ADEV_NAME "mlx5_core"
enum {
MLX5_BOARD_ID_LEN = 64,
};
......@@ -534,6 +537,17 @@ struct mlx5_core_roce {
struct mlx5_flow_handle *allow_rule;
};
enum {
MLX5_PRIV_FLAGS_DISABLE_IB_ADEV = 1 << 0,
MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV = 1 << 1,
};
struct mlx5_adev {
struct auxiliary_device adev;
struct mlx5_core_dev *mdev;
int idx;
};
struct mlx5_priv {
/* IRQ table valid only for real pci devices PF or VF */
struct mlx5_irq_table *irq_table;
......@@ -571,6 +585,8 @@ struct mlx5_priv {
struct list_head dev_list;
struct list_head ctx_list;
spinlock_t ctx_lock;
struct mlx5_adev **adev;
int adev_idx;
struct mlx5_events *events;
struct mlx5_flow_steering *steering;
......@@ -578,6 +594,7 @@ struct mlx5_priv {
struct mlx5_eswitch *eswitch;
struct mlx5_core_sriov sriov;
struct mlx5_lag *lag;
u32 flags;
struct mlx5_devcom *devcom;
struct mlx5_fw_reset *fw_reset;
struct mlx5_core_roce roce;
......@@ -1055,23 +1072,6 @@ enum {
MAX_MR_CACHE_ENTRIES
};
enum {
MLX5_INTERFACE_PROTOCOL_IB = 0,
MLX5_INTERFACE_PROTOCOL_ETH = 1,
MLX5_INTERFACE_PROTOCOL_VDPA = 2,
};
struct mlx5_interface {
void * (*add)(struct mlx5_core_dev *dev);
void (*remove)(struct mlx5_core_dev *dev, void *context);
int (*attach)(struct mlx5_core_dev *dev, void *context);
void (*detach)(struct mlx5_core_dev *dev, void *context);
int protocol;
struct list_head list;
};
int mlx5_register_interface(struct mlx5_interface *intf);
void mlx5_unregister_interface(struct mlx5_interface *intf);
int mlx5_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb);
int mlx5_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *nb);
int mlx5_eq_notifier_register(struct mlx5_core_dev *dev, struct mlx5_nb *nb);
......
......@@ -96,10 +96,10 @@ static inline u32 mlx5_eswitch_get_vport_metadata_mask(void)
u32 mlx5_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw,
u16 vport_num);
u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw);
u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev);
#else /* CONFIG_MLX5_ESWITCH */
static inline u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw)
static inline u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev)
{
return MLX5_ESWITCH_NONE;
}
......@@ -136,4 +136,8 @@ mlx5_eswitch_get_vport_metadata_mask(void)
}
#endif /* CONFIG_MLX5_ESWITCH */
static inline bool is_mdev_switchdev_mode(struct mlx5_core_dev *dev)
{
return mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS;
}
#endif
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2020 Mellanox Technologies Ltd. */
#ifndef __MLX5_VDPA_IFC_H_
#define __MLX5_VDPA_IFC_H_
#include <linux/mlx5/mlx5_ifc.h>
#ifndef __MLX5_IFC_VDPA_H_
#define __MLX5_IFC_VDPA_H_
enum {
MLX5_VIRTIO_Q_EVENT_MODE_NO_MSIX_MODE = 0x0,
......@@ -165,4 +163,4 @@ struct mlx5_ifc_modify_virtio_net_q_out_bits {
struct mlx5_ifc_general_obj_out_cmd_hdr_bits general_obj_out_cmd_hdr;
};
#endif /* __MLX5_VDPA_IFC_H_ */
#endif /* __MLX5_IFC_VDPA_H_ */
......@@ -838,4 +838,12 @@ struct mhi_device_id {
kernel_ulong_t driver_data;
};
#define AUXILIARY_NAME_SIZE 32
#define AUXILIARY_MODULE_PREFIX "auxiliary:"
struct auxiliary_device_id {
char name[AUXILIARY_NAME_SIZE];
kernel_ulong_t driver_data;
};
#endif /* LINUX_MOD_DEVICETABLE_H */
......@@ -243,5 +243,8 @@ int main(void)
DEVID(mhi_device_id);
DEVID_FIELD(mhi_device_id, chan);
DEVID(auxiliary_device_id);
DEVID_FIELD(auxiliary_device_id, name);
return 0;
}
......@@ -1364,6 +1364,13 @@ static int do_mhi_entry(const char *filename, void *symval, char *alias)
{
DEF_FIELD_ADDR(symval, mhi_device_id, chan);
sprintf(alias, MHI_DEVICE_MODALIAS_FMT, *chan);
return 1;
}
static int do_auxiliary_entry(const char *filename, void *symval, char *alias)
{
DEF_FIELD_ADDR(symval, auxiliary_device_id, name);
sprintf(alias, AUXILIARY_MODULE_PREFIX "%s", *name);
return 1;
}
......@@ -1442,6 +1449,7 @@ static const struct devtable devtable[] = {
{"tee", SIZE_tee_client_device_id, do_tee_entry},
{"wmi", SIZE_wmi_device_id, do_wmi_entry},
{"mhi", SIZE_mhi_device_id, do_mhi_entry},
{"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry},
};
/* Create MODULE_ALIAS() statements.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment