public inbox for linux-doc@vger.kernel.org
 help / color / mirror / Atom feed
From: Mohsin Bashir <mohsin.bashr@gmail.com>
To: "illusion.wang" <illusion.wang@nebula-matrix.com>,
	dimon.zhao@nebula-matrix.com, alvin.wang@nebula-matrix.com,
	sam.chen@nebula-matrix.com, netdev@vger.kernel.org
Cc: andrew+netdev@lunn.ch, corbet@lwn.net, kuba@kernel.org,
	linux-doc@vger.kernel.org, lorenzo@kernel.org, pabeni@redhat.com,
	horms@kernel.org, vadim.fedorenko@linux.dev,
	lukas.bulwahn@redhat.com, edumazet@google.com,
	enelsonmoore@gmail.com, skhan@linuxfoundation.org,
	hkallweit1@gmail.com, jani.nikula@intel.com,
	open list <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v10 net-next 02/11] net/nebula-matrix: add our driver architecture
Date: Thu, 2 Apr 2026 02:02:44 -0700	[thread overview]
Message-ID: <bf9f7c6f-8759-4f4f-8e35-2bd7c446d102@gmail.com> (raw)
In-Reply-To: <20260401022318.28550-3-illusion.wang@nebula-matrix.com>



On 3/31/26 7:23 PM, illusion.wang wrote:
> our driver architecture:
> Hardware (HW), Channel, Resource, Dispatch, and Device Layer
> Struct Initialization/Deinitialization, and Operation Set Registration/
> Unregistration
> 
> Our driver architecture is relatively complex because the code is highly
> reusable and designed to support multiple features. Additionally, the
> codebase supports multiple chip variants, each with distinct
> hardware-software interactions.
> To ensure compatibility, our architecture is divided into the following
> layers:
> 
> 1. Dev Layer (Device Layer)
> The top-level business logic layer where all operations are
> device-centric. Every operation is performed relative to the device
> context. The intergration of base functions encompasses:
> management(ctrl only for leonis pf0), network(net_dev,this time not
> contained),common.
> 
> 2. Dispatch Layer
> The distribution from services to specific data operations is mainly
> divided into two types: direct pass-through and handling by the
> management PF. It shields the upper layer from the differences in
> specific underlying locations.
> It describes the processing locations and paths of the services.
> 
> 3. Resource Layer
> Handles tasks dispatched from Dispatch Layer. These tasks fall into two
> categories:
> 3.1 Hardware control
> The Resource Layer further invokes the HW Layer when hardware access is
> needed, as only the HW Layer has OS-level privileges.
> 3.2 Software resource management
> Operations like packet statistics collection that don't require hardware
> access.
> 
> 4. HW Layer (Hardware Layer)
> Serves the Resource Layer by interacting with different hardware
> chipsets.Writes to hardware registers to drive the hardware based on
> Resource Layer directives.
> 
> 5. Channel Layer
> 
> Handle communication between PF0(has ctrl func) and other PF,and provide
> basic interaction channels.
> 
> 6. Common Layer
> Provides fundamental services
> 
> Signed-off-by: illusion.wang <illusion.wang@nebula-matrix.com>
> ---
>   .../net/ethernet/nebula-matrix/nbl/Makefile   |   7 +-
>   .../nbl/nbl_channel/nbl_channel.c             |  82 ++++++++
>   .../nbl/nbl_channel/nbl_channel.h             |  29 +++
>   .../net/ethernet/nebula-matrix/nbl/nbl_core.h |  43 +++++
>   .../nebula-matrix/nbl/nbl_core/nbl_dev.c      |  56 ++++++
>   .../nebula-matrix/nbl/nbl_core/nbl_dev.h      |  27 +++
>   .../nebula-matrix/nbl/nbl_core/nbl_dispatch.c |  75 ++++++++
>   .../nebula-matrix/nbl/nbl_core/nbl_dispatch.h |  25 +++
>   .../nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.c  | 140 ++++++++++++++
>   .../nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.h  |  14 ++
>   .../nbl_hw_leonis/nbl_resource_leonis.c       |  83 ++++++++
>   .../nbl_hw_leonis/nbl_resource_leonis.h       |  10 +
>   .../nebula-matrix/nbl/nbl_hw/nbl_hw_reg.h     |  68 +++++++
>   .../nebula-matrix/nbl/nbl_hw/nbl_resource.h   |  30 +++
>   .../nbl/nbl_include/nbl_def_channel.h         |  26 +++
>   .../nbl/nbl_include/nbl_def_common.h          |  35 ++++
>   .../nbl/nbl_include/nbl_def_dev.h             |  16 ++
>   .../nbl/nbl_include/nbl_def_dispatch.h        |  29 +++
>   .../nbl/nbl_include/nbl_def_hw.h              |  22 +++
>   .../nbl/nbl_include/nbl_def_resource.h        |  20 ++
>   .../nbl/nbl_include/nbl_include.h             |  11 ++
>   .../nbl/nbl_include/nbl_product_base.h        |  18 ++
>   .../net/ethernet/nebula-matrix/nbl/nbl_main.c | 179 ++++++++++++++++++
>   23 files changed, 1044 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.c
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dev.c
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dev.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.c
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.c
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_resource_leonis.c
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_resource_leonis.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_reg.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_resource.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_channel.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_common.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_dev.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_dispatch.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_hw.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_resource.h
>   create mode 100644 drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_product_base.h
> 
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/Makefile b/drivers/net/ethernet/nebula-matrix/nbl/Makefile
> index b90fba239401..271605920396 100644
> --- a/drivers/net/ethernet/nebula-matrix/nbl/Makefile
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/Makefile
> @@ -3,4 +3,9 @@
>   
>   obj-$(CONFIG_NBL) := nbl.o
>   
> -nbl-objs +=      nbl_main.o
> +nbl-objs +=       nbl_channel/nbl_channel.o \
> +				nbl_hw/nbl_hw_leonis/nbl_hw_leonis.o \
> +				nbl_hw/nbl_hw_leonis/nbl_resource_leonis.o \
> +				nbl_core/nbl_dispatch.o \
> +				nbl_core/nbl_dev.o \
> +				nbl_main.o
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.c b/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.c
> new file mode 100644
> index 000000000000..9f4603870cb4
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.c
> @@ -0,0 +1,82 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/pci.h>
> +#include "nbl_channel.h"
> +
> +static struct nbl_channel_ops chan_ops = {
> +};
> +
> +static struct nbl_channel_mgt *
> +nbl_chan_setup_chan_mgt(struct nbl_adapter *adapter)
> +{
> +	struct nbl_hw_ops_tbl *hw_ops_tbl = adapter->intf.hw_ops_tbl;
> +	struct nbl_common_info *common = &adapter->common;
> +	struct device *dev = &adapter->pdev->dev;
> +	struct nbl_chan_info *mailbox;
> +	struct nbl_channel_mgt *chan_mgt;

Reverse xmas violation here

> +
> +	chan_mgt = devm_kzalloc(dev, sizeof(*chan_mgt), GFP_KERNEL);
> +	if (!chan_mgt)
> +		return ERR_PTR(-ENOMEM);
> +
> +	chan_mgt->common = common;
> +	chan_mgt->hw_ops_tbl = hw_ops_tbl;
> +
> +	mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL);
> +	if (!mailbox)
> +		return ERR_PTR(-ENOMEM);

Here, if mailbox allocation fails, we return without freeing chan_mgt 
resulting in a leak.

> +	mailbox->chan_type = NBL_CHAN_TYPE_MAILBOX;
> +	chan_mgt->chan_info[NBL_CHAN_TYPE_MAILBOX] = mailbox;
> +
> +	return chan_mgt;
> +}
> +
> +static struct nbl_channel_ops_tbl *
> +nbl_chan_setup_ops(struct device *dev, struct nbl_channel_mgt *chan_mgt)
> +{
> +	struct nbl_channel_ops_tbl *chan_ops_tbl;
> +
> +	chan_ops_tbl = devm_kzalloc(dev, sizeof(*chan_ops_tbl), GFP_KERNEL);
> +	if (!chan_ops_tbl)
> +		return ERR_PTR(-ENOMEM);
> +
> +	chan_ops_tbl->ops = &chan_ops;
> +	chan_ops_tbl->priv = chan_mgt;
> +
> +	return chan_ops_tbl;
> +}
> +
> +int nbl_chan_init_common(struct nbl_adapter *adap)
> +{
> +	struct nbl_channel_ops_tbl *chan_ops_tbl;
> +	struct device *dev = &adap->pdev->dev;
> +	struct nbl_channel_mgt *chan_mgt;
> +	int ret;
> +
> +	chan_mgt = nbl_chan_setup_chan_mgt(adap);
> +	if (IS_ERR(chan_mgt)) {
> +		ret = PTR_ERR(chan_mgt);
> +		goto setup_mgt_fail;
> +	}
> +	adap->core.chan_mgt = chan_mgt;
> +
> +	chan_ops_tbl = nbl_chan_setup_ops(dev, chan_mgt);
> +	if (IS_ERR(chan_ops_tbl)) {
> +		ret = PTR_ERR(chan_ops_tbl);
> +		goto setup_ops_fail;
> +	}
> +	adap->intf.channel_ops_tbl = chan_ops_tbl;
> +	return 0;
> +
> +setup_ops_fail:
> +setup_mgt_fail:
> +	return ret;
> +}

Why do we need two labels here? Looks like some piece of code will use 
two different clean-up paths in the later patches. Better to add related 
label then?

> +
> +void nbl_chan_remove_common(struct nbl_adapter *adap)
> +{
> +}
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.h
> new file mode 100644
> index 000000000000..637912d1e806
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_CHANNEL_H_
> +#define _NBL_CHANNEL_H_
> +
> +#include <linux/types.h>
> +
> +#include "../nbl_include/nbl_include.h"
> +#include "../nbl_include/nbl_product_base.h"
> +#include "../nbl_include/nbl_def_channel.h"
> +#include "../nbl_include/nbl_def_hw.h"
> +#include "../nbl_include/nbl_def_common.h"
> +#include "../nbl_core.h"
> +
> +struct nbl_chan_info {
> +	u8 chan_type;
> +};
> +
> +struct nbl_channel_mgt {
> +	struct nbl_common_info *common;
> +	struct nbl_hw_ops_tbl *hw_ops_tbl;
> +	struct nbl_chan_info *chan_info[NBL_CHAN_TYPE_MAX];
> +	struct nbl_hash_tbl_mgt *handle_hash_tbl;
> +};
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_core.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core.h
> index c525114297b4..aa4d24d04e2c 100644
> --- a/drivers/net/ethernet/nebula-matrix/nbl/nbl_core.h
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core.h
> @@ -6,6 +6,20 @@
>   #ifndef _NBL_CORE_H_
>   #define _NBL_CORE_H_
>   
> +#include <linux/pci.h>
> +#include "nbl_include/nbl_def_common.h"
> +#include "nbl_include/nbl_include.h"
> +
> +struct nbl_hw_mgt;
> +struct nbl_hw_ops_tbl;
> +struct nbl_resource_mgt;
> +struct nbl_resource_ops_tbl;
> +struct nbl_dispatch_mgt;
> +struct nbl_dispatch_ops_tbl;
> +struct nbl_channel_ops_tbl;
> +struct nbl_channel_mgt;
> +struct nbl_dev_mgt;
> +
>   enum {
>   	NBL_CAP_HAS_CTRL_BIT,
>   	NBL_CAP_HAS_NET_BIT,
> @@ -13,4 +27,33 @@ enum {
>   	NBL_CAP_IS_LEONIS_BIT,
>   };
>   
> +struct nbl_interface {
> +	struct nbl_hw_ops_tbl *hw_ops_tbl;
> +	struct nbl_resource_ops_tbl *resource_ops_tbl;
> +	struct nbl_dispatch_ops_tbl *dispatch_ops_tbl;
> +	struct nbl_channel_ops_tbl *channel_ops_tbl;
> +};
> +
> +struct nbl_core {
> +	struct nbl_hw_mgt *hw_mgt;
> +	struct nbl_resource_mgt *res_mgt;
> +	struct nbl_dispatch_mgt *disp_mgt;
> +	struct nbl_dev_mgt *dev_mgt;
> +	struct nbl_channel_mgt *chan_mgt;
> +};
> +
> +struct nbl_adapter {
> +	struct pci_dev *pdev;
> +	struct nbl_core core;
> +	struct nbl_interface intf;
> +	struct nbl_common_info common;
> +	struct nbl_product_base_ops *product_base_ops;
> +};
> +
> +struct nbl_adapter *nbl_core_init(struct pci_dev *pdev,
> +				  struct nbl_init_param *param);
> +void nbl_core_remove(struct nbl_adapter *adapter);
> +int nbl_core_start(struct nbl_adapter *adapter);
> +void nbl_core_stop(struct nbl_adapter *adapter);
> +
>   #endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dev.c b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dev.c
> new file mode 100644
> index 000000000000..5deb21e35f8e
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dev.c
> @@ -0,0 +1,56 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +#include <linux/device.h>
> +#include <linux/pci.h>
> +#include "nbl_dev.h"
> +
> +static struct nbl_dev_mgt *nbl_dev_setup_dev_mgt(struct nbl_common_info *common)
> +{
> +	struct nbl_dev_mgt *dev_mgt;
> +
> +	dev_mgt = devm_kzalloc(common->dev, sizeof(*dev_mgt), GFP_KERNEL);
> +	if (!dev_mgt)
> +		return ERR_PTR(-ENOMEM);
> +
> +	dev_mgt->common = common;
> +	return dev_mgt;
> +}
> +
> +int nbl_dev_init(struct nbl_adapter *adapter)
> +{
> +	struct nbl_common_info *common = &adapter->common;
> +	struct nbl_dispatch_ops_tbl *disp_ops_tbl =
> +		adapter->intf.dispatch_ops_tbl;
> +	struct nbl_channel_ops_tbl *chan_ops_tbl =
> +		adapter->intf.channel_ops_tbl;
> +	struct nbl_dev_mgt *dev_mgt;
> +	int ret;
> +
> +	dev_mgt = nbl_dev_setup_dev_mgt(common);
> +	if (IS_ERR(dev_mgt)) {
> +		ret = PTR_ERR(dev_mgt);
> +		return ret;
> +	}
> +
> +	dev_mgt->disp_ops_tbl = disp_ops_tbl;
> +	dev_mgt->chan_ops_tbl = chan_ops_tbl;
> +	adapter->core.dev_mgt = dev_mgt;
> +
> +	return 0;
> +}
> +
> +void nbl_dev_remove(struct nbl_adapter *adapter)
> +{
> +}
> +
> +/* ----------  Dev start process  ---------- */
> +int nbl_dev_start(struct nbl_adapter *adapter)
> +{
> +	return 0;
> +}
> +
> +void nbl_dev_stop(struct nbl_adapter *adapter)
> +{
> +}
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dev.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dev.h
> new file mode 100644
> index 000000000000..9b71092b99a0
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dev.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_DEV_H_
> +#define _NBL_DEV_H_
> +
> +#include <linux/types.h>
> +
> +#include "../nbl_include/nbl_include.h"
> +#include "../nbl_include/nbl_product_base.h"
> +#include "../nbl_include/nbl_def_channel.h"
> +#include "../nbl_include/nbl_def_hw.h"
> +#include "../nbl_include/nbl_def_resource.h"
> +#include "../nbl_include/nbl_def_dispatch.h"
> +#include "../nbl_include/nbl_def_dev.h"
> +#include "../nbl_include/nbl_def_common.h"
> +#include "../nbl_core.h"
> +
> +struct nbl_dev_mgt {
> +	struct nbl_common_info *common;
> +	struct nbl_dispatch_ops_tbl *disp_ops_tbl;
> +	struct nbl_channel_ops_tbl *chan_ops_tbl;
> +};
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.c b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.c
> new file mode 100644
> index 000000000000..8b031f6e963f
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.c
> @@ -0,0 +1,75 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +#include <linux/device.h>
> +#include <linux/pci.h>
> +#include "nbl_dispatch.h"
> +
> +static struct nbl_dispatch_mgt *
> +nbl_disp_setup_disp_mgt(struct nbl_common_info *common)
> +{
> +	struct nbl_dispatch_mgt *disp_mgt;
> +	struct device *dev = common->dev;
> +
> +	disp_mgt = devm_kzalloc(dev, sizeof(*disp_mgt), GFP_KERNEL);
> +	if (!disp_mgt)
> +		return ERR_PTR(-ENOMEM);
> +
> +	disp_mgt->common = common;
> +	return disp_mgt;
> +}
> +
> +static struct nbl_dispatch_ops_tbl *
> +nbl_disp_setup_ops(struct device *dev, struct nbl_dispatch_mgt *disp_mgt)
> +{
> +	struct nbl_dispatch_ops_tbl *disp_ops_tbl;
> +	struct nbl_dispatch_ops *disp_ops;
> +
> +	disp_ops_tbl = devm_kzalloc(dev, sizeof(*disp_ops_tbl), GFP_KERNEL);
> +	if (!disp_ops_tbl)
> +		return ERR_PTR(-ENOMEM);
> +
> +	disp_ops =
> +		devm_kzalloc(dev, sizeof(*disp_ops), GFP_KERNEL);
> +	if (!disp_ops)
> +		return ERR_PTR(-ENOMEM);
> +
> +	disp_ops_tbl->ops = disp_ops;
> +	disp_ops_tbl->priv = disp_mgt;
> +
> +	return disp_ops_tbl;
> +}
> +
> +int nbl_disp_init(struct nbl_adapter *adapter)
> +{
> +	struct nbl_common_info *common = &adapter->common;
> +	struct nbl_dispatch_ops_tbl *disp_ops_tbl;
> +	struct nbl_resource_ops_tbl *res_ops_tbl =
> +		adapter->intf.resource_ops_tbl;
> +	struct nbl_channel_ops_tbl *chan_ops_tbl =
> +		adapter->intf.channel_ops_tbl;
> +	struct device *dev = &adapter->pdev->dev;
> +	struct nbl_dispatch_mgt *disp_mgt;
> +	int ret;
> +
> +	disp_mgt = nbl_disp_setup_disp_mgt(common);
> +	if (IS_ERR(disp_mgt)) {
> +		ret = PTR_ERR(disp_mgt);
> +		return ret;
> +	}
> +
> +	disp_ops_tbl = nbl_disp_setup_ops(dev, disp_mgt);
> +	if (IS_ERR(disp_ops_tbl)) {
> +		ret = PTR_ERR(disp_ops_tbl);
> +		return ret;
> +	}
> +
> +	disp_mgt->res_ops_tbl = res_ops_tbl;
> +	disp_mgt->chan_ops_tbl = chan_ops_tbl;
> +	disp_mgt->disp_ops_tbl = disp_ops_tbl;
> +	adapter->core.disp_mgt = disp_mgt;
> +	adapter->intf.dispatch_ops_tbl = disp_ops_tbl;
> +
> +	return 0;
> +}
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.h
> new file mode 100644
> index 000000000000..fa7f4597febe
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.h
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_DISPATCH_H_
> +#define _NBL_DISPATCH_H_
> +#include "../nbl_include/nbl_include.h"
> +#include "../nbl_include/nbl_product_base.h"
> +#include "../nbl_include/nbl_def_channel.h"
> +#include "../nbl_include/nbl_def_hw.h"
> +#include "../nbl_include/nbl_def_resource.h"
> +#include "../nbl_include/nbl_def_dispatch.h"
> +#include "../nbl_include/nbl_def_common.h"
> +#include "../nbl_core.h"
> +
> +struct nbl_dispatch_mgt {
> +	struct nbl_common_info *common;
> +	struct nbl_resource_ops_tbl *res_ops_tbl;
> +	struct nbl_channel_ops_tbl *chan_ops_tbl;
> +	struct nbl_dispatch_ops_tbl *disp_ops_tbl;
> +	DECLARE_BITMAP(ctrl_lvl, NBL_DISP_CTRL_LVL_MAX);
> +};
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.c b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.c
> new file mode 100644
> index 000000000000..6dd8d3a087dd
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.c
> @@ -0,0 +1,140 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +#include <linux/device.h>
> +#include <linux/pci.h>
> +#include <linux/bits.h>
> +#include <linux/io.h>
> +#include <linux/spinlock.h>
> +#include "nbl_hw_leonis.h"
> +
> +static struct nbl_hw_ops hw_ops = {
> +};
> +
> +/* Structure starts here, adding an op should not modify anything below */
> +static struct nbl_hw_mgt *nbl_hw_setup_hw_mgt(struct nbl_common_info *common)
> +{
> +	struct device *dev = common->dev;
> +	struct nbl_hw_mgt *hw_mgt;
> +
> +	hw_mgt = devm_kzalloc(dev, sizeof(*hw_mgt), GFP_KERNEL);
> +	if (!hw_mgt)
> +		return ERR_PTR(-ENOMEM);
> +
> +	hw_mgt->common = common;
> +
> +	return hw_mgt;
> +}
> +
> +static struct nbl_hw_ops_tbl *nbl_hw_setup_ops(struct nbl_common_info *common,
> +					       struct nbl_hw_mgt *hw_mgt)
> +{
> +	struct nbl_hw_ops_tbl *hw_ops_tbl;
> +	struct device *dev;
> +
> +	dev = common->dev;
> +	hw_ops_tbl =
> +		devm_kzalloc(dev, sizeof(*hw_ops_tbl), GFP_KERNEL);
> +	if (!hw_ops_tbl)
> +		return ERR_PTR(-ENOMEM);
> +
> +	hw_ops_tbl->ops = &hw_ops;
> +	hw_ops_tbl->priv = hw_mgt;
> +
> +	return hw_ops_tbl;
> +}
> +
> +int nbl_hw_init_leonis(struct nbl_adapter *adapter)
> +{
> +	struct nbl_common_info *common = &adapter->common;
> +	struct pci_dev *pdev = common->pdev;
> +	struct nbl_hw_ops_tbl *hw_ops_tbl;
> +	struct nbl_hw_mgt *hw_mgt;
> +	int bar_mask;
> +	int ret;
> +
> +	hw_mgt = nbl_hw_setup_hw_mgt(common);
> +	if (IS_ERR(hw_mgt)) {
> +		ret = PTR_ERR(hw_mgt);
> +		goto setup_mgt_fail;
> +	}
> +	bar_mask = BIT(NBL_MEMORY_BAR) | BIT(NBL_MAILBOX_BAR);
> +	ret = pci_request_selected_regions(pdev, bar_mask, NBL_DRIVER_NAME);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Request memory bar and mailbox bar failed, err = %d\n",
> +			ret);
> +		goto request_bar_region_fail;
> +	}
> +
> +	if (common->has_ctrl) {
> +		hw_mgt->hw_addr =
> +			ioremap(pci_resource_start(pdev, NBL_MEMORY_BAR),
> +				pci_resource_len(pdev, NBL_MEMORY_BAR) -
> +					NBL_RDMA_NOTIFY_OFF);
> +		if (!hw_mgt->hw_addr) {
> +			dev_err(&pdev->dev, "Memory bar ioremap failed\n");
> +			ret = -EIO;
> +			goto ioremap_err;
> +		}
> +		hw_mgt->hw_size = pci_resource_len(pdev, NBL_MEMORY_BAR) -
> +				  NBL_RDMA_NOTIFY_OFF;
> +	} else {
> +		hw_mgt->hw_addr =
> +			ioremap(pci_resource_start(pdev, NBL_MEMORY_BAR),
> +				NBL_RDMA_NOTIFY_OFF);
> +		if (!hw_mgt->hw_addr) {
> +			dev_err(&pdev->dev, "Memory bar ioremap failed\n");
> +			ret = -EIO;
> +			goto ioremap_err;
> +		}
> +		hw_mgt->hw_size = NBL_RDMA_NOTIFY_OFF;
> +	}
> +
> +	hw_mgt->notify_offset = 0;
> +	hw_mgt->mailbox_bar_hw_addr = pci_ioremap_bar(pdev, NBL_MAILBOX_BAR);
> +	if (!hw_mgt->mailbox_bar_hw_addr) {
> +		dev_err(&pdev->dev, "Mailbox bar ioremap failed\n");
> +		ret = -EIO;
> +		goto mailbox_ioremap_err;
> +	}
> +
> +	spin_lock_init(&hw_mgt->reg_lock);
> +	adapter->core.hw_mgt = hw_mgt;
> +
> +	hw_ops_tbl = nbl_hw_setup_ops(common, hw_mgt);
> +	if (IS_ERR(hw_ops_tbl)) {
> +		ret = PTR_ERR(hw_ops_tbl);
> +		goto setup_ops_fail;
> +	}
> +	adapter->intf.hw_ops_tbl = hw_ops_tbl;
> +
> +	return 0;
> +
> +setup_ops_fail:
> +	iounmap(hw_mgt->mailbox_bar_hw_addr);
> +mailbox_ioremap_err:
> +	iounmap(hw_mgt->hw_addr);
> +ioremap_err:
> +	pci_release_selected_regions(pdev, bar_mask);
> +request_bar_region_fail:
> +setup_mgt_fail:
> +	return ret;
> +}
> +
> +void nbl_hw_remove_leonis(struct nbl_adapter *adapter)
> +{
> +	int bar_mask = BIT(NBL_MEMORY_BAR) | BIT(NBL_MAILBOX_BAR);
> +	struct nbl_common_info *common = &adapter->common;
> +	struct nbl_hw_mgt *hw_mgt = adapter->core.hw_mgt;
> +	u8 __iomem *hw_addr = hw_mgt->hw_addr;
> +	struct pci_dev *pdev = common->pdev;
> +	u8 __iomem *mailbox_bar_hw_addr;
> +
> +	mailbox_bar_hw_addr = hw_mgt->mailbox_bar_hw_addr;
> +
> +	iounmap(mailbox_bar_hw_addr);
> +	iounmap(hw_addr);
> +	pci_release_selected_regions(pdev, bar_mask);
> +}
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.h
> new file mode 100644
> index 000000000000..77c67b67ba31
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_HW_LEONIS_H_
> +#define _NBL_HW_LEONIS_H_
> +
> +#include <linux/types.h>
> +
> +#include "../../nbl_include/nbl_include.h"
> +#include "../nbl_hw_reg.h"
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_resource_leonis.c b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_resource_leonis.c
> new file mode 100644
> index 000000000000..355f7ea66b88
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_resource_leonis.c
> @@ -0,0 +1,83 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +#include <linux/device.h>
> +#include <linux/pci.h>
> +#include "nbl_resource_leonis.h"
> +
> +static struct nbl_resource_ops res_ops = {
> +};
> +
> +static struct nbl_resource_mgt *
> +nbl_res_setup_res_mgt(struct nbl_common_info *common)
> +{
> +	struct nbl_resource_info *resource_info;
> +	struct nbl_resource_mgt *res_mgt;
> +	struct device *dev = common->dev;
> +
> +	res_mgt = devm_kzalloc(dev, sizeof(*res_mgt), GFP_KERNEL);
> +	if (!res_mgt)
> +		return ERR_PTR(-ENOMEM);
> +	res_mgt->common = common;
> +
> +	resource_info =
> +		devm_kzalloc(dev, sizeof(*resource_info), GFP_KERNEL);
> +	if (!resource_info)
> +		return ERR_PTR(-ENOMEM);
> +	res_mgt->resource_info = resource_info;
> +
> +	return res_mgt;
> +}
> +
> +static struct nbl_resource_ops_tbl *
> +nbl_res_setup_ops(struct device *dev, struct nbl_resource_mgt *res_mgt)
> +{
> +	struct nbl_resource_ops_tbl *res_ops_tbl;
> +
> +	res_ops_tbl = devm_kzalloc(dev, sizeof(*res_ops_tbl), GFP_KERNEL);
> +	if (!res_ops_tbl)
> +		return ERR_PTR(-ENOMEM);
> +
> +	res_ops_tbl->ops = &res_ops;
> +	res_ops_tbl->priv = res_mgt;
> +
> +	return res_ops_tbl;
> +}
> +
> +static int nbl_res_start(struct nbl_resource_mgt *res_mgt)
> +{
> +	return 0;
> +}
> +
> +int nbl_res_init_leonis(struct nbl_adapter *adap)
> +{
> +	struct nbl_channel_ops_tbl *chan_ops_tbl = adap->intf.channel_ops_tbl;
> +	struct nbl_hw_ops_tbl *hw_ops_tbl = adap->intf.hw_ops_tbl;
> +	struct nbl_common_info *common = &adap->common;
> +	struct nbl_resource_ops_tbl *res_ops_tbl;
> +	struct device *dev = &adap->pdev->dev;
> +	struct nbl_resource_mgt *res_mgt;
> +	int ret;
> +
> +	res_mgt = nbl_res_setup_res_mgt(common);
> +	if (IS_ERR(res_mgt)) {
> +		ret = PTR_ERR(res_mgt);
> +		return ret;
> +	}
> +	res_mgt->chan_ops_tbl = chan_ops_tbl;
> +	res_mgt->hw_ops_tbl = hw_ops_tbl;
> +
> +	ret = nbl_res_start(res_mgt);
> +	if (ret)
> +		return ret;
> +	adap->core.res_mgt = res_mgt;
> +
> +	res_ops_tbl = nbl_res_setup_ops(dev, res_mgt);
> +	if (IS_ERR(res_ops_tbl)) {
> +		ret = PTR_ERR(res_ops_tbl);
> +		return ret;
> +	}
> +	adap->intf.resource_ops_tbl = res_ops_tbl;
> +	return 0;
> +}
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_resource_leonis.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_resource_leonis.h
> new file mode 100644
> index 000000000000..4e61a5c141e5
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_leonis/nbl_resource_leonis.h
> @@ -0,0 +1,10 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_RESOURCE_LEONIS_H_
> +#define _NBL_RESOURCE_LEONIS_H_
> +
> +#include "../nbl_resource.h"
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_reg.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_reg.h
> new file mode 100644
> index 000000000000..46e58b4e73dc
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_hw_reg.h
> @@ -0,0 +1,68 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_HW_REG_H_
> +#define _NBL_HW_REG_H_
> +
> +#include <linux/types.h>
> +
> +#include "../nbl_include/nbl_product_base.h"
> +#include "../nbl_include/nbl_def_channel.h"
> +#include "../nbl_include/nbl_def_hw.h"
> +#include "../nbl_include/nbl_def_common.h"
> +#include "../nbl_core.h"
> +
> +#define NBL_MEMORY_BAR				0
> +#define NBL_MAILBOX_BAR				2
> +#define NBL_RDMA_NOTIFY_OFF			8192
> +#define NBL_HW_DUMMY_REG			0x1300904
> +
> +struct nbl_hw_mgt {
> +	struct nbl_common_info *common;
> +	u8 __iomem *hw_addr;
> +	u8 __iomem *mailbox_bar_hw_addr;
> +	u64 notify_offset;
> +	u32 version;
> +	u32 hw_size;
> +	spinlock_t reg_lock; /* Protect reg access */
> +};
> +
> +static inline u32 rd32(u8 __iomem *addr, u64 reg)
> +{
> +	return readl(addr + reg);
> +}
> +
> +static inline void wr32(u8 __iomem *addr, u64 reg, u32 value)
> +{
> +	writel(value, addr + reg);
> +}
> +
> +static inline void nbl_hw_wr32(struct nbl_hw_mgt *hw_mgt, u64 reg, u32 value)
> +{
> +	/* Used for emu, make sure that we won't write too frequently */
> +	wr32(hw_mgt->hw_addr, reg, value);
> +}
> +
> +static inline u32 nbl_hw_rd32(struct nbl_hw_mgt *hw_mgt, u64 reg)
> +{
> +	return rd32(hw_mgt->hw_addr, reg);
> +}
> +
> +static inline void nbl_mbx_wr32(struct nbl_hw_mgt *hw_mgt, u64 reg, u32 value)
> +{
> +	writel(value, hw_mgt->mailbox_bar_hw_addr + reg);
> +}
> +
> +static inline void nbl_flush_writes(struct nbl_hw_mgt *hw_mgt)
> +{
> +	nbl_hw_rd32(hw_mgt, NBL_HW_DUMMY_REG);
> +}
> +
> +static inline u32 nbl_mbx_rd32(struct nbl_hw_mgt *hw_mgt, u64 reg)
> +{
> +	return readl(hw_mgt->mailbox_bar_hw_addr + reg);
> +}
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_resource.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_resource.h
> new file mode 100644
> index 000000000000..e08b6237da32
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_hw/nbl_resource.h
> @@ -0,0 +1,30 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_RESOURCE_H_
> +#define _NBL_RESOURCE_H_
> +
> +#include <linux/types.h>
> +
> +#include "../nbl_include/nbl_include.h"
> +#include "../nbl_include/nbl_product_base.h"
> +#include "../nbl_include/nbl_def_channel.h"
> +#include "../nbl_include/nbl_def_hw.h"
> +#include "../nbl_include/nbl_def_resource.h"
> +#include "../nbl_include/nbl_def_common.h"
> +#include "../nbl_core.h"
> +
> +struct nbl_resource_info {
> +};
> +
> +struct nbl_resource_mgt {
> +	struct nbl_common_info *common;
> +	struct nbl_resource_info *resource_info;
> +	struct nbl_channel_ops_tbl *chan_ops_tbl;
> +	struct nbl_hw_ops_tbl *hw_ops_tbl;
> +	struct nbl_interrupt_mgt *intr_mgt;
> +};
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_channel.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_channel.h
> new file mode 100644
> index 000000000000..ff03a53b9f5d
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_channel.h
> @@ -0,0 +1,26 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_DEF_CHANNEL_H_
> +#define _NBL_DEF_CHANNEL_H_
> +
> +struct nbl_channel_mgt;
> +struct nbl_adapter;
> +enum nbl_channel_type {
> +	NBL_CHAN_TYPE_MAILBOX,
> +	NBL_CHAN_TYPE_MAX
> +};
> +
> +struct nbl_channel_ops {
> +};
> +
> +struct nbl_channel_ops_tbl {
> +	struct nbl_channel_ops *ops;
> +	struct nbl_channel_mgt *priv;
> +};
> +
> +int nbl_chan_init_common(struct nbl_adapter *adapter);
> +void nbl_chan_remove_common(struct nbl_adapter *adapter);
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_common.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_common.h
> new file mode 100644
> index 000000000000..cc73d6a91f3c
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_common.h
> @@ -0,0 +1,35 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_DEF_COMMON_H_
> +#define _NBL_DEF_COMMON_H_
> +
> +#include <linux/types.h>
> +#include <linux/pci.h>
> +#include <linux/device.h>
> +#include "nbl_include.h"
> +
> +struct nbl_common_info {
> +	struct pci_dev *pdev;
> +	struct device *dev;
> +	u32 msg_enable;
> +	u16 vsi_id;
> +	u8 eth_id;
> +	u8 logic_eth_id;
> +	u8 eth_mode;
> +
> +	u8 function;
> +	u8 devid;
> +	u8 bus;
> +	u8 hw_bus;
> +	u16 mgt_pf;
> +
> +	bool pci_using_dac;
> +	enum nbl_product_type product_type;
> +	u8 has_ctrl;
> +	u8 has_net;
> +};
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_dev.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_dev.h
> new file mode 100644
> index 000000000000..32e6cce38d39
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_dev.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_DEF_DEV_H_
> +#define _NBL_DEF_DEV_H_
> +
> +struct nbl_adapter;
> +
> +int nbl_dev_init(struct nbl_adapter *adapter);
> +void nbl_dev_remove(struct nbl_adapter *adapter);
> +int nbl_dev_start(struct nbl_adapter *adapter);
> +void nbl_dev_stop(struct nbl_adapter *adapter);
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_dispatch.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_dispatch.h
> new file mode 100644
> index 000000000000..2230c728079e
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_dispatch.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_DEF_DISPATCH_H_
> +#define _NBL_DEF_DISPATCH_H_
> +
> +struct nbl_dispatch_mgt;
> +struct nbl_adapter;
> +enum {
> +	NBL_DISP_CTRL_LVL_NEVER = 0,
> +	NBL_DISP_CTRL_LVL_MGT,
> +	NBL_DISP_CTRL_LVL_NET,
> +	NBL_DISP_CTRL_LVL_ALWAYS,
> +	NBL_DISP_CTRL_LVL_MAX,
> +};
> +
> +struct nbl_dispatch_ops {
> +};
> +
> +struct nbl_dispatch_ops_tbl {
> +	struct nbl_dispatch_ops *ops;
> +	struct nbl_dispatch_mgt *priv;
> +};
> +
> +int nbl_disp_init(struct nbl_adapter *adapter);
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_hw.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_hw.h
> new file mode 100644
> index 000000000000..168504b30973
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_hw.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_DEF_HW_H_
> +#define _NBL_DEF_HW_H_
> +
> +struct nbl_hw_mgt;
> +struct nbl_adapter;
> +struct nbl_hw_ops {
> +};
> +
> +struct nbl_hw_ops_tbl {
> +	struct nbl_hw_ops *ops;
> +	struct nbl_hw_mgt *priv;
> +};
> +
> +int nbl_hw_init_leonis(struct nbl_adapter *adapter);
> +void nbl_hw_remove_leonis(struct nbl_adapter *adapter);
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_resource.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_resource.h
> new file mode 100644
> index 000000000000..16add7e25eae
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_def_resource.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_DEF_RESOURCE_H_
> +#define _NBL_DEF_RESOURCE_H_
> +
> +struct nbl_resource_mgt;
> +struct nbl_adapter;
> +struct nbl_resource_ops {
> +};
> +
> +struct nbl_resource_ops_tbl {
> +	struct nbl_resource_ops *ops;
> +	struct nbl_resource_mgt *priv;
> +};
> +
> +int nbl_res_init_leonis(struct nbl_adapter *adapter);
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_include.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_include.h
> index 1046e6517b15..50f30f756bf3 100644
> --- a/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_include.h
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_include.h
> @@ -11,6 +11,11 @@
>   /*  ------  Basic definitions  -------  */
>   #define NBL_DRIVER_NAME					"nbl"
>   
> +enum nbl_product_type {
> +	NBL_LEONIS_TYPE,
> +	NBL_PRODUCT_MAX,
> +};
> +
>   struct nbl_func_caps {
>   	u32 has_ctrl:1;
>   	u32 has_net:1;
> @@ -18,4 +23,10 @@ struct nbl_func_caps {
>   	u32 rsv:29;
>   };
>   
> +struct nbl_init_param {
> +	struct nbl_func_caps caps;
> +	enum nbl_product_type product_type;
> +	bool pci_using_dac;
> +};
> +
>   #endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_product_base.h b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_product_base.h
> new file mode 100644
> index 000000000000..4368d4f57a03
> --- /dev/null
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_include/nbl_product_base.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2025 Nebula Matrix Limited.
> + */
> +
> +#ifndef _NBL_DEF_PRODUCT_BASE_H_
> +#define _NBL_DEF_PRODUCT_BASE_H_
> +
> +struct nbl_adapter;
> +struct nbl_product_base_ops {
> +	int (*hw_init)(struct nbl_adapter *p);
> +	void (*hw_remove)(struct nbl_adapter *p);
> +	int (*res_init)(struct nbl_adapter *p);
> +	int (*chan_init)(struct nbl_adapter *p);
> +	void (*chan_remove)(struct nbl_adapter *p);
> +};
> +
> +#endif
> diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_main.c b/drivers/net/ethernet/nebula-matrix/nbl/nbl_main.c
> index 10c3536b327b..db035136e09c 100644
> --- a/drivers/net/ethernet/nebula-matrix/nbl/nbl_main.c
> +++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_main.c
> @@ -6,17 +6,196 @@
>   #include <linux/device.h>
>   #include <linux/pci.h>
>   #include <linux/module.h>
> +#include <linux/bits.h>
>   #include "nbl_include/nbl_include.h"
> +#include "nbl_include/nbl_product_base.h"
> +#include "nbl_include/nbl_def_channel.h"
> +#include "nbl_include/nbl_def_hw.h"
> +#include "nbl_include/nbl_def_resource.h"
> +#include "nbl_include/nbl_def_dispatch.h"
> +#include "nbl_include/nbl_def_dev.h"
> +#include "nbl_include/nbl_def_common.h"
>   #include "nbl_core.h"
>   
> +static struct nbl_product_base_ops nbl_product_base_ops[NBL_PRODUCT_MAX] = {
> +	{
> +		.hw_init	= nbl_hw_init_leonis,
> +		.hw_remove	= nbl_hw_remove_leonis,
> +		.res_init	= nbl_res_init_leonis,
> +		.chan_init	= nbl_chan_init_common,
> +		.chan_remove	= nbl_chan_remove_common,
> +	},
> +};
> +
> +int nbl_core_start(struct nbl_adapter *adapter)
> +{
> +	return nbl_dev_start(adapter);
> +}
> +
> +void nbl_core_stop(struct nbl_adapter *adapter)
> +{
> +	nbl_dev_stop(adapter);
> +}
> +
> +static struct nbl_product_base_ops *
> +nbl_core_setup_product_ops(struct nbl_adapter *adapter,
> +			   struct nbl_init_param *param)
> +{
> +	adapter->product_base_ops = &nbl_product_base_ops[param->product_type];
> +	return adapter->product_base_ops;
> +}
> +
> +struct nbl_adapter *nbl_core_init(struct pci_dev *pdev,
> +				  struct nbl_init_param *param)
> +{
> +	struct nbl_product_base_ops *product_base_ops;
> +	struct nbl_common_info *common;
> +	struct nbl_adapter *adapter;
> +	int ret;
> +
> +	adapter = devm_kzalloc(&pdev->dev, sizeof(*adapter), GFP_KERNEL);
> +	if (!adapter)
> +		return NULL;
> +
> +	adapter->pdev = pdev;
> +	common = &adapter->common;
> +
> +	common->pdev = pdev;
> +	common->dev = &pdev->dev;
> +	common->has_ctrl = param->caps.has_ctrl;
> +	common->has_net = param->caps.has_net;
> +	common->pci_using_dac = param->pci_using_dac;
> +	common->function = PCI_FUNC(pdev->devfn);
> +	common->devid = PCI_SLOT(pdev->devfn);
> +	common->bus = pdev->bus->number;
> +	common->product_type = param->product_type;
> +
> +	product_base_ops = nbl_core_setup_product_ops(adapter, param);
> +
> +	/*
> +	 *every product's hw/chan/res layer has a great difference,
> +	 *so call their own init ops
> +	 */
> +	ret = product_base_ops->hw_init(adapter);
> +	if (ret)
> +		goto hw_init_fail;
> +
> +	ret = product_base_ops->chan_init(adapter);
> +	if (ret)
> +		goto chan_init_fail;
> +
> +	ret = product_base_ops->res_init(adapter);
> +	if (ret)
> +		goto res_init_fail;
> +
> +	ret = nbl_disp_init(adapter);
> +	if (ret)
> +		goto res_init_fail;
> +
> +	ret = nbl_dev_init(adapter);
> +	if (ret)
> +		goto res_init_fail;
> +	return adapter;
> +

All the potential failures after res_init() do not need any other cleanup?

> +res_init_fail:
> +	product_base_ops->chan_remove(adapter);
> +chan_init_fail:
> +	product_base_ops->hw_remove(adapter);
> +hw_init_fail:
> +	return NULL;
> +}
> +
> +void nbl_core_remove(struct nbl_adapter *adapter)
> +{
> +	struct nbl_product_base_ops *product_base_ops;
> +
> +	product_base_ops = adapter->product_base_ops;
> +	nbl_dev_remove(adapter);
> +	product_base_ops->chan_remove(adapter);
> +	product_base_ops->hw_remove(adapter);
> +}
> +
> +static void nbl_get_func_param(struct pci_dev *pdev, kernel_ulong_t driver_data,
> +			       struct nbl_init_param *param)
> +{
> +	param->caps.has_ctrl = !!(driver_data & BIT(NBL_CAP_HAS_CTRL_BIT));
> +	param->caps.has_net = !!(driver_data & BIT(NBL_CAP_HAS_NET_BIT));
> +	param->caps.is_nic = !!(driver_data & BIT(NBL_CAP_IS_NIC_BIT));
> +
> +	if (!!(driver_data & BIT(NBL_CAP_IS_LEONIS_BIT)))
> +		param->product_type = NBL_LEONIS_TYPE;
> +
> +	/*
> +	 * Leonis only PF0 has ctrl capability, but PF0's pcie device_id
> +	 * is same with other PF.So handle it special.
> +	 */
> +	if (param->product_type == NBL_LEONIS_TYPE &&
> +	    (PCI_FUNC(pdev->devfn) == 0))
> +		param->caps.has_ctrl = 1;
> +}
> +
>   static int nbl_probe(struct pci_dev *pdev,
>   		     const struct pci_device_id *id)
>   {
> +	struct nbl_init_param param = { { 0 } };
> +	struct device *dev = &pdev->dev;
> +	struct nbl_adapter *adapter;
> +	int err;
> +
> +	if (pci_enable_device(pdev)) {
> +		dev_err(&pdev->dev, "Failed to enable PCI device\n");
> +		return -ENODEV;
> +	}
> +
> +	param.pci_using_dac = true;
> +	nbl_get_func_param(pdev, id->driver_data, &param);
> +
> +	err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> +	if (err) {
> +		dev_dbg(dev, "Configure DMA 64 bit mask failed, err = %d\n",
> +			err);
> +		param.pci_using_dac = false;
> +		err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
> +		if (err) {
> +			dev_err(dev,
> +				"Configure DMA 32 bit mask failed, err = %d\n",
> +				err);
> +			goto configure_dma_err;
> +		}
> +	}
> +	pci_set_master(pdev);
> +	pci_save_state(pdev);
> +	adapter = nbl_core_init(pdev, &param);
> +	if (!adapter) {
> +		dev_err(dev, "Nbl adapter init fail\n");
> +		err = -ENOMEM;
> +		goto adapter_init_err;
> +	}
> +	pci_set_drvdata(pdev, adapter);
> +	err = nbl_core_start(adapter);
> +	if (err)
> +		goto core_start_err;
>   	return 0;
> +core_start_err:
> +	nbl_core_remove(adapter);
> +adapter_init_err:
> +	pci_clear_master(pdev);
> +configure_dma_err:
> +	pci_disable_device(pdev);
> +	return err;
>   }
>   
>   static void nbl_remove(struct pci_dev *pdev)
>   {
> +	struct nbl_adapter *adapter = pci_get_drvdata(pdev);
> +
> +	pci_disable_sriov(pdev);
> +
> +	nbl_core_stop(adapter);
> +	nbl_core_remove(adapter);
> +
> +	pci_clear_master(pdev);
> +	pci_disable_device(pdev);
>   }
>   
>   /*

  reply	other threads:[~2026-04-02  9:02 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-01  2:23 [PATCH v10 net-next 00/11] nbl driver for Nebulamatrix NICs illusion.wang
2026-04-01  2:23 ` [PATCH v10 net-next 01/11] net/nebula-matrix: add minimum nbl build framework illusion.wang
2026-04-01  2:23 ` [PATCH v10 net-next 02/11] net/nebula-matrix: add our driver architecture illusion.wang
2026-04-02  9:02   ` Mohsin Bashir [this message]
2026-04-01  2:23 ` [PATCH v10 net-next 03/11] net/nebula-matrix: add chip related definitions illusion.wang
2026-04-01  2:23 ` [PATCH v10 net-next 04/11] net/nebula-matrix: channel msg value and msg struct illusion.wang
2026-04-02  9:03   ` Mohsin Bashir
2026-04-01  2:23 ` [PATCH v10 net-next 05/11] net/nebula-matrix: add channel layer illusion.wang
2026-04-02  9:04   ` Mohsin Bashir
2026-04-01  2:23 ` [PATCH v10 net-next 06/11] net/nebula-matrix: add common resource implementation illusion.wang
2026-04-02  9:05   ` Mohsin Bashir
2026-04-01  2:23 ` [PATCH v10 net-next 07/11] net/nebula-matrix: add intr " illusion.wang
2026-04-02  9:05   ` Mohsin Bashir
2026-04-01  2:23 ` [PATCH v10 net-next 08/11] net/nebula-matrix: add vsi " illusion.wang
2026-04-02  9:06   ` Mohsin Bashir
2026-04-01  2:23 ` [PATCH v10 net-next 09/11] net/nebula-matrix: add Dispatch layer implementation illusion.wang
2026-04-01  2:23 ` [PATCH v10 net-next 10/11] net/nebula-matrix: add common/ctrl dev init/reinit operation illusion.wang
2026-04-01  2:23 ` [PATCH v10 net-next 11/11] net/nebula-matrix: add common dev start/stop operation illusion.wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bf9f7c6f-8759-4f4f-8e35-2bd7c446d102@gmail.com \
    --to=mohsin.bashr@gmail.com \
    --cc=alvin.wang@nebula-matrix.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=corbet@lwn.net \
    --cc=dimon.zhao@nebula-matrix.com \
    --cc=edumazet@google.com \
    --cc=enelsonmoore@gmail.com \
    --cc=hkallweit1@gmail.com \
    --cc=horms@kernel.org \
    --cc=illusion.wang@nebula-matrix.com \
    --cc=jani.nikula@intel.com \
    --cc=kuba@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lorenzo@kernel.org \
    --cc=lukas.bulwahn@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sam.chen@nebula-matrix.com \
    --cc=skhan@linuxfoundation.org \
    --cc=vadim.fedorenko@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox