Commit a69839d4 authored by Long Li's avatar Long Li Committed by Leon Romanovsky

net: mana: Add support for auxiliary device

In preparation for supporting MANA RDMA driver, add support for auxiliary
device in the Ethernet driver. The RDMA device is modeled as an auxiliary
device to the Ethernet device.
Reviewed-by: default avatarDexuan Cui <decui@microsoft.com>
Signed-off-by: default avatarLong Li <longli@microsoft.com>
Link: https://lore.kernel.org/r/1667502990-2559-2-git-send-email-longli@linuxonhyperv.comAcked-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
parent 30a0b95b
......@@ -19,6 +19,7 @@ config MICROSOFT_MANA
tristate "Microsoft Azure Network Adapter (MANA) support"
depends on PCI_MSI && X86_64
depends on PCI_HYPERV
select AUXILIARY_BUS
help
This driver supports Microsoft Azure Network Adapter (MANA).
So far, the driver is only supported on X86_64.
......
......@@ -204,6 +204,8 @@ struct gdma_dev {
/* GDMA driver specific pointer */
void *driver_data;
struct auxiliary_device *adev;
};
#define MINIMUM_SUPPORTED_PAGE_SIZE PAGE_SIZE
......
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2022, Microsoft Corporation. */
#include "mana.h"
#include <linux/auxiliary_bus.h>
struct mana_adev {
struct auxiliary_device adev;
struct gdma_dev *mdev;
};
......@@ -13,6 +13,19 @@
#include <net/ip6_checksum.h>
#include "mana.h"
#include "mana_auxiliary.h"
static DEFINE_IDA(mana_adev_ida);
static int mana_adev_idx_alloc(void)
{
return ida_alloc(&mana_adev_ida, GFP_KERNEL);
}
static void mana_adev_idx_free(int idx)
{
ida_free(&mana_adev_ida, idx);
}
/* Microsoft Azure Network Adapter (MANA) functions */
......@@ -2106,6 +2119,69 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
return err;
}
static void adev_release(struct device *dev)
{
struct mana_adev *madev = container_of(dev, struct mana_adev, adev.dev);
kfree(madev);
}
static void remove_adev(struct gdma_dev *gd)
{
struct auxiliary_device *adev = gd->adev;
int id = adev->id;
auxiliary_device_delete(adev);
auxiliary_device_uninit(adev);
mana_adev_idx_free(id);
gd->adev = NULL;
}
static int add_adev(struct gdma_dev *gd)
{
struct auxiliary_device *adev;
struct mana_adev *madev;
int ret;
madev = kzalloc(sizeof(*madev), GFP_KERNEL);
if (!madev)
return -ENOMEM;
adev = &madev->adev;
ret = mana_adev_idx_alloc();
if (ret < 0)
goto idx_fail;
adev->id = ret;
adev->name = "rdma";
adev->dev.parent = gd->gdma_context->dev;
adev->dev.release = adev_release;
madev->mdev = gd;
ret = auxiliary_device_init(adev);
if (ret)
goto init_fail;
ret = auxiliary_device_add(adev);
if (ret)
goto add_fail;
gd->adev = adev;
return 0;
add_fail:
auxiliary_device_uninit(adev);
init_fail:
mana_adev_idx_free(adev->id);
idx_fail:
kfree(madev);
return ret;
}
int mana_probe(struct gdma_dev *gd, bool resuming)
{
struct gdma_context *gc = gd->gdma_context;
......@@ -2173,6 +2249,8 @@ int mana_probe(struct gdma_dev *gd, bool resuming)
break;
}
}
err = add_adev(gd);
out:
if (err)
mana_remove(gd, false);
......@@ -2189,6 +2267,10 @@ void mana_remove(struct gdma_dev *gd, bool suspending)
int err;
int i;
/* adev currently doesn't support suspending, always remove it */
if (gd->adev)
remove_adev(gd);
for (i = 0; i < ac->num_ports; i++) {
ndev = ac->ports[i];
if (!ndev) {
......@@ -2221,7 +2303,6 @@ void mana_remove(struct gdma_dev *gd, bool suspending)
}
mana_destroy_eq(ac);
out:
mana_gd_deregister_device(gd);
......
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