[PATCH net-next 1/4] ionic: register auxiliary devices from a table of device types

From: Nikhil P. Rao

Date: Tue Nov 03 2026 - 14:20:10 EST


A later patch adds a hardware monitoring auxiliary device alongside the
rdma one. Describe the auxiliary device types in a table, so that adding
one takes an enum value and a table entry.

Allocate the auxiliary device id once per ionic device instead of on
every add, so all of a device's auxiliary devices share one id, for
example ionic.rdma.0 and ionic.hwmon.0.

Reviewed-by: Brett Creeley <brett.creeley@xxxxxxx>
Signed-off-by: Nikhil P. Rao <nikhil.rao@xxxxxxx>
---
drivers/net/ethernet/pensando/ionic/ionic.h | 1 +
drivers/net/ethernet/pensando/ionic/ionic_aux.c | 94 +++++++++++++++-------
drivers/net/ethernet/pensando/ionic/ionic_aux.h | 2 +-
.../net/ethernet/pensando/ionic/ionic_bus_pci.c | 14 +++-
drivers/net/ethernet/pensando/ionic/ionic_lif.h | 7 +-
5 files changed, 86 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h
index 85198e6a806e6..555a77db1b1e7 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic.h
@@ -49,6 +49,7 @@ struct ionic {
struct ionic_identity ident;
struct workqueue_struct *wq;
struct ionic_lif *lif;
+ int aux_id;
unsigned int nnqs_per_lif;
unsigned int neqs_per_lif;
unsigned int ntxqs_per_lif;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_aux.c b/drivers/net/ethernet/pensando/ionic/ionic_aux.c
index 4f193d0ee87ad..370a7eff3e283 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_aux.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_aux.c
@@ -6,41 +6,47 @@
#include "ionic_lif.h"
#include "ionic_aux.h"

-static DEFINE_IDA(aux_ida);
+struct ionic_aux_type_info {
+ const char *name;
+ bool (*supported)(struct ionic *ionic);
+ int (*prepare)(struct ionic *ionic);
+};
+
+static bool ionic_rdma_supported(struct ionic *ionic)
+{
+ return le64_to_cpu(ionic->ident.lif.capabilities) & IONIC_LIF_CAP_RDMA;
+}
+
+static const struct ionic_aux_type_info ionic_aux_types[IONIC_AUX_MAX] = {
+ [IONIC_AUX_RDMA] = {
+ .name = "rdma",
+ .supported = ionic_rdma_supported,
+ },
+};

static void ionic_auxbus_release(struct device *dev)
{
struct ionic_aux_dev *ionic_adev;

ionic_adev = container_of(dev, struct ionic_aux_dev, adev.dev);
- ida_free(&aux_ida, ionic_adev->adev.id);
kfree(ionic_adev);
}

-int ionic_auxbus_register(struct ionic_lif *lif)
+static struct ionic_aux_dev *ionic_auxbus_add(struct ionic_lif *lif,
+ const char *name)
{
struct ionic_aux_dev *ionic_adev;
struct auxiliary_device *aux_dev;
- int err, id;
-
- if (!(le64_to_cpu(lif->ionic->ident.lif.capabilities) & IONIC_LIF_CAP_RDMA))
- return 0;
+ int err;

ionic_adev = kzalloc_obj(*ionic_adev);
if (!ionic_adev)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);

aux_dev = &ionic_adev->adev;

- id = ida_alloc(&aux_ida, GFP_KERNEL);
- if (id < 0) {
- dev_err(lif->ionic->dev, "Failed to allocate aux id: %d\n", id);
- kfree(ionic_adev);
- return id;
- }
-
- aux_dev->id = id;
- aux_dev->name = "rdma";
+ aux_dev->id = lif->ionic->aux_id;
+ aux_dev->name = name;
aux_dev->dev.parent = &lif->ionic->pdev->dev;
aux_dev->dev.release = ionic_auxbus_release;
ionic_adev->lif = lif;
@@ -48,9 +54,8 @@ int ionic_auxbus_register(struct ionic_lif *lif)
if (err) {
dev_err(lif->ionic->dev, "Failed to initialize %s aux device: %d\n",
aux_dev->name, err);
- ida_free(&aux_ida, id);
kfree(ionic_adev);
- return err;
+ return ERR_PTR(err);
}

err = auxiliary_device_add(aux_dev);
@@ -58,24 +63,57 @@ int ionic_auxbus_register(struct ionic_lif *lif)
dev_err(lif->ionic->dev, "Failed to add %s aux device: %d\n",
aux_dev->name, err);
auxiliary_device_uninit(aux_dev);
- return err;
+ return ERR_PTR(err);
+ }
+
+ return ionic_adev;
+}
+
+static void ionic_auxbus_del(struct ionic_aux_dev *ionic_adev)
+{
+ auxiliary_device_delete(&ionic_adev->adev);
+ auxiliary_device_uninit(&ionic_adev->adev);
+}
+
+void ionic_auxbus_register(struct ionic_lif *lif)
+{
+ const struct ionic_aux_type_info *type;
+ struct ionic_aux_dev *ionic_adev;
+ int i;
+
+ mutex_lock(&lif->adev_lock);
+
+ for (i = 0; i < IONIC_AUX_MAX; i++) {
+ type = &ionic_aux_types[i];
+
+ if (!type->supported(lif->ionic))
+ continue;
+
+ if (type->prepare && type->prepare(lif->ionic))
+ continue;
+
+ ionic_adev = ionic_auxbus_add(lif, type->name);
+ if (!IS_ERR(ionic_adev))
+ lif->aux_devs[i] = ionic_adev;
}

- lif->ionic_adev = ionic_adev;
- return 0;
+ mutex_unlock(&lif->adev_lock);
}

void ionic_auxbus_unregister(struct ionic_lif *lif)
{
+ int i;
+
mutex_lock(&lif->adev_lock);
- if (!lif->ionic_adev)
- goto out;

- auxiliary_device_delete(&lif->ionic_adev->adev);
- auxiliary_device_uninit(&lif->ionic_adev->adev);
+ for (i = IONIC_AUX_MAX - 1; i >= 0; i--) {
+ if (!lif->aux_devs[i])
+ continue;
+
+ ionic_auxbus_del(lif->aux_devs[i]);
+ lif->aux_devs[i] = NULL;
+ }

- lif->ionic_adev = NULL;
-out:
mutex_unlock(&lif->adev_lock);
}

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_aux.h b/drivers/net/ethernet/pensando/ionic/ionic_aux.h
index f5528a9f187db..215f2f67646be 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_aux.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_aux.h
@@ -4,7 +4,7 @@
#ifndef _IONIC_AUX_H_
#define _IONIC_AUX_H_

-int ionic_auxbus_register(struct ionic_lif *lif);
+void ionic_auxbus_register(struct ionic_lif *lif);
void ionic_auxbus_unregister(struct ionic_lif *lif);

#endif /* _IONIC_AUX_H_ */
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
index ddc2f9770df45..9bedcb7224abc 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
@@ -20,6 +20,8 @@ static const struct pci_device_id ionic_id_table[] = {
};
MODULE_DEVICE_TABLE(pci, ionic_id_table);

+static DEFINE_IDA(ionic_ida);
+
int ionic_bus_get_irq(struct ionic *ionic, unsigned int num)
{
return pci_irq_vector(ionic->pdev, num);
@@ -321,12 +323,17 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, ionic);
mutex_init(&ionic->dev_cmd_lock);

+ err = ida_alloc(&ionic_ida, GFP_KERNEL);
+ if (err < 0)
+ goto err_out;
+ ionic->aux_id = err;
+
/* Query system for DMA addressing limitation for the device. */
err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(IONIC_ADDR_LEN));
if (err) {
dev_err(dev, "Unable to obtain 64-bit DMA for consistent allocations, aborting. err=%d\n",
err);
- goto err_out;
+ goto err_out_free_id;
}

#ifdef CONFIG_PPC64
@@ -336,7 +343,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

err = ionic_setup_one(ionic);
if (err)
- goto err_out;
+ goto err_out_free_id;

/* Allocate and init the LIF */
err = ionic_lif_size(ionic);
@@ -401,6 +408,8 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ionic_dev_teardown(ionic);
ionic_clear_pci(ionic);
ionic_debugfs_del_dev(ionic);
+err_out_free_id:
+ ida_free(&ionic_ida, ionic->aux_id);
err_out:
mutex_destroy(&ionic->dev_cmd_lock);
ionic_devlink_free(ionic);
@@ -437,6 +446,7 @@ static void ionic_remove(struct pci_dev *pdev)
ionic_dev_teardown(ionic);
ionic_clear_pci(ionic);
ionic_debugfs_del_dev(ionic);
+ ida_free(&ionic_ida, ionic->aux_id);
mutex_destroy(&ionic->dev_cmd_lock);
ionic_devlink_free(ionic);
}
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
index e790f6b9441e2..d04503b19c513 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -180,6 +180,11 @@ struct ionic_qtype_info {

struct ionic_phc;

+enum ionic_aux_type {
+ IONIC_AUX_RDMA,
+ IONIC_AUX_MAX,
+};
+
#define IONIC_LIF_NAME_MAX_SZ 32
struct ionic_lif {
struct net_device *netdev;
@@ -225,7 +230,7 @@ struct ionic_lif {
dma_addr_t info_pa;
u32 info_sz;
struct ionic_qtype_info qtype_info[IONIC_QTYPE_MAX];
- struct ionic_aux_dev *ionic_adev;
+ struct ionic_aux_dev *aux_devs[IONIC_AUX_MAX];
struct mutex adev_lock; /* lock for aux_dev actions */

u8 rss_hash_key[IONIC_RSS_HASH_KEY_SIZE];

--
2.43.0