[PATCH v7 04/10] PCI: endpoint: Add pci-epf-ntb.h for the shared NTB control layout

From: Koichiro Den

Date: Wed Oct 21 2026 - 00:24:48 EST


Currently, pci-epf-ntb.c and pci-epf-vntb.c each define struct
epf_ntb_ctrl, and ntb_hw_epf.c mirrors the same layout with hard-coded
register offsets.

Move the shared struct and macros to include/linux/pci-epf-ntb.h. The
vNTB "reserved" field takes the pci-epf-ntb.c name mw1_offset, which is
what ntb_hw_epf.c reads at that offset.

No functional changes.

Suggested-by: Frank Li <Frank.Li@xxxxxxx>
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
Changes since v6:
- Move the ntb_hw_epf conversion to a separate patch. (Frank)
- Link to v6: https://lore.kernel.org/r/20261020054948.1218370-5-den@xxxxxxxxxxxxx/

MAINTAINERS | 1 +
drivers/pci/endpoint/functions/pci-epf-ntb.c | 85 ++++--------
drivers/pci/endpoint/functions/pci-epf-vntb.c | 131 +++++++-----------
include/linux/pci-epf-ntb.h | 48 +++++++
4 files changed, 128 insertions(+), 137 deletions(-)
create mode 100644 include/linux/pci-epf-ntb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f58a305de664..855d2a6f59cd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19916,6 +19916,7 @@ F: drivers/ntb/
F: drivers/pci/endpoint/functions/pci-epf-*ntb.c
F: include/linux/ntb.h
F: include/linux/ntb_transport.h
+F: include/linux/pci-epf-ntb.h
F: tools/testing/selftests/ntb/

NTB INTEL DRIVER
diff --git a/drivers/pci/endpoint/functions/pci-epf-ntb.c b/drivers/pci/endpoint/functions/pci-epf-ntb.c
index 5314aca2188a..925cf46219d7 100644
--- a/drivers/pci/endpoint/functions/pci-epf-ntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-ntb.c
@@ -41,27 +41,13 @@

#include <linux/pci-epc.h>
#include <linux/pci-epf.h>
+#include <linux/pci-epf-ntb.h>

static struct workqueue_struct *kpcintb_workqueue;

-#define COMMAND_CONFIGURE_DOORBELL 1
-#define COMMAND_TEARDOWN_DOORBELL 2
-#define COMMAND_CONFIGURE_MW 3
-#define COMMAND_TEARDOWN_MW 4
-#define COMMAND_LINK_UP 5
-#define COMMAND_LINK_DOWN 6
-
-#define COMMAND_STATUS_OK 1
-#define COMMAND_STATUS_ERROR 2
-
-#define LINK_STATUS_UP BIT(0)
-
#define SPAD_COUNT 64
#define DB_COUNT 4
#define NTB_MW_OFFSET 2
-#define DB_COUNT_MASK GENMASK(15, 0)
-#define MSIX_ENABLE BIT(16)
-#define MAX_DB_COUNT 32
#define MAX_MW 4

enum epf_ntb_bar {
@@ -104,23 +90,6 @@ struct epf_ntb_epc {
const struct pci_epc_features *epc_features;
};

-struct epf_ntb_ctrl {
- u32 command;
- u32 argument;
- u16 command_status;
- u16 link_status;
- u32 topology;
- u64 addr;
- u64 size;
- u32 num_mws;
- u32 mw1_offset;
- u32 spad_offset;
- u32 spad_count;
- u32 db_entry_size;
- u32 db_data[MAX_DB_COUNT];
- u32 db_offset[MAX_DB_COUNT];
-} __packed;
-
static struct pci_epf_header epf_ntb_header = {
.vendorid = PCI_ANY_ID,
.deviceid = PCI_ANY_ID,
@@ -156,9 +125,9 @@ static int epf_ntb_link_up(struct epf_ntb *ntb, bool link_up)
is_msix = ntb_epc->is_msix;
ctrl = ntb_epc->reg;
if (link_up)
- ctrl->link_status |= LINK_STATUS_UP;
+ ctrl->link_status |= EPF_NTB_LINK_STATUS_UP;
else
- ctrl->link_status &= ~LINK_STATUS_UP;
+ ctrl->link_status &= ~EPF_NTB_LINK_STATUS_UP;
irq_type = is_msix ? PCI_IRQ_MSIX : PCI_IRQ_MSI;
ret = pci_epc_raise_irq(epc, func_no, vfunc_no, irq_type, 1);
if (ret) {
@@ -562,9 +531,9 @@ static int epf_ntb_configure_db(struct epf_ntb *ntb,
ntb_epc = ntb->epc[type];
epc = ntb_epc->epc;

- if (!db_count || db_count > MAX_DB_COUNT) {
+ if (!db_count || db_count > EPF_NTB_MAX_DB_COUNT) {
dev_err(&epc->dev, "DB count %d out of range (1 - %d)\n",
- db_count, MAX_DB_COUNT);
+ db_count, EPF_NTB_MAX_DB_COUNT);
return -EINVAL;
}

@@ -648,50 +617,52 @@ static void epf_ntb_cmd_handler(struct work_struct *work)
dev = &ntb->epf->dev;

switch (command) {
- case COMMAND_CONFIGURE_DOORBELL:
- db_count = argument & DB_COUNT_MASK;
- is_msix = argument & MSIX_ENABLE;
+ case EPF_NTB_COMMAND_CONFIGURE_DOORBELL:
+ db_count = argument & EPF_NTB_DB_COUNT_MASK;
+ is_msix = argument & EPF_NTB_MSIX_ENABLE;
ret = epf_ntb_configure_db(ntb, type, db_count, is_msix);
if (ret < 0)
- ctrl->command_status = COMMAND_STATUS_ERROR;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_ERROR;
else
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
- case COMMAND_TEARDOWN_DOORBELL:
+ case EPF_NTB_COMMAND_TEARDOWN_DOORBELL:
epf_ntb_teardown_db(ntb, type);
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
- case COMMAND_CONFIGURE_MW:
+ case EPF_NTB_COMMAND_CONFIGURE_MW:
ret = epf_ntb_configure_mw(ntb, type, argument);
if (ret < 0)
- ctrl->command_status = COMMAND_STATUS_ERROR;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_ERROR;
else
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
- case COMMAND_TEARDOWN_MW:
+ case EPF_NTB_COMMAND_TEARDOWN_MW:
epf_ntb_teardown_mw(ntb, type, argument);
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
- case COMMAND_LINK_UP:
+ case EPF_NTB_COMMAND_LINK_UP:
ntb_epc->linkup = true;
if (ntb->epc[PRIMARY_INTERFACE]->linkup &&
ntb->epc[SECONDARY_INTERFACE]->linkup) {
ret = epf_ntb_link_up(ntb, true);
if (ret < 0)
- ctrl->command_status = COMMAND_STATUS_ERROR;
+ ctrl->command_status =
+ EPF_NTB_COMMAND_STATUS_ERROR;
else
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status =
+ EPF_NTB_COMMAND_STATUS_OK;
goto reset_handler;
}
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
- case COMMAND_LINK_DOWN:
+ case EPF_NTB_COMMAND_LINK_DOWN:
ntb_epc->linkup = false;
ret = epf_ntb_link_up(ntb, false);
if (ret < 0)
- ctrl->command_status = COMMAND_STATUS_ERROR;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_ERROR;
else
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
default:
dev_err(dev, "%s intf UNKNOWN command: %d\n",
@@ -1298,9 +1269,9 @@ static int epf_ntb_configure_interrupt(struct epf_ntb *ntb,
func_no = ntb_epc->func_no;
vfunc_no = ntb_epc->vfunc_no;

- if (!ntb->db_count || ntb->db_count > MAX_DB_COUNT) {
+ if (!ntb->db_count || ntb->db_count > EPF_NTB_MAX_DB_COUNT) {
dev_err(dev, "DB count %d out of range (1 - %d)\n",
- ntb->db_count, MAX_DB_COUNT);
+ ntb->db_count, EPF_NTB_MAX_DB_COUNT);
return -EINVAL;
}

diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
index 1a0ce31e680c..3adbaa9d85db 100644
--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
@@ -47,27 +47,14 @@
#include <linux/pci-ep-msi.h>
#include <linux/pci-epc.h>
#include <linux/pci-epf.h>
+#include <linux/pci-epf-ntb.h>
#include <linux/ntb.h>

static struct workqueue_struct *kpcintb_workqueue;

-#define COMMAND_CONFIGURE_DOORBELL 1
-#define COMMAND_TEARDOWN_DOORBELL 2
-#define COMMAND_CONFIGURE_MW 3
-#define COMMAND_TEARDOWN_MW 4
-#define COMMAND_LINK_UP 5
-#define COMMAND_LINK_DOWN 6
-
-#define COMMAND_STATUS_OK 1
-#define COMMAND_STATUS_ERROR 2
-
-#define LINK_STATUS_UP BIT(0)
-
#define SPAD_COUNT 64
#define DB_COUNT 4
#define NTB_MW_OFFSET 2
-#define DB_COUNT_MASK GENMASK(15, 0)
-#define MSIX_ENABLE BIT(16)
#define MAX_MW 4

/* Limit per-work execution to avoid monopolizing kworker on doorbell storms. */
@@ -90,47 +77,6 @@ enum epf_irq_slot {
};

#define MIN_DB_COUNT (EPF_IRQ_DB_START + 1)
-#define MAX_DB_COUNT 32
-
-/*
- * +--------------------------------------------------+ Base
- * | |
- * | |
- * | |
- * | Common Control Register |
- * | |
- * | |
- * | |
- * +-----------------------+--------------------------+ Base+spad_offset
- * | | |
- * | Peer Spad Space | Spad Space |
- * | | |
- * | | |
- * +-----------------------+--------------------------+ Base+spad_offset
- * | | | +spad_count * 4
- * | | |
- * | Spad Space | Peer Spad Space |
- * | | |
- * +-----------------------+--------------------------+
- * Virtual PCI PCIe Endpoint
- * NTB Driver NTB Driver
- */
-struct epf_ntb_ctrl {
- u32 command;
- u32 argument;
- u16 command_status;
- u16 link_status;
- u32 topology;
- u64 addr;
- u64 size;
- u32 num_mws;
- u32 reserved;
- u32 spad_offset;
- u32 spad_count;
- u32 db_entry_size;
- u32 db_data[MAX_DB_COUNT];
- u32 db_offset[MAX_DB_COUNT];
-} __packed;

struct epf_ntb {
struct ntb_dev *ntb;
@@ -195,9 +141,9 @@ static void epf_ntb_update_link(struct epf_ntb *ntb)

/* The link is usable only after both sides have enabled it. */
if (ntb->host_link_enabled && ntb->vhost_link_enabled)
- link_status |= LINK_STATUS_UP;
+ link_status |= EPF_NTB_LINK_STATUS_UP;
else
- link_status &= ~LINK_STATUS_UP;
+ link_status &= ~EPF_NTB_LINK_STATUS_UP;

WRITE_ONCE(ntb->reg->link_status, link_status);
}
@@ -368,45 +314,47 @@ static void epf_ntb_cmd_handler(struct work_struct *work)
dev = &ntb->epf->dev;

switch (command) {
- case COMMAND_CONFIGURE_DOORBELL:
+ case EPF_NTB_COMMAND_CONFIGURE_DOORBELL:
epc_features = pci_epc_get_features(ntb->epf->epc,
ntb->epf->func_no,
ntb->epf->vfunc_no);
- if (((argument & MSIX_ENABLE) && !epc_features->msix_capable) ||
- (!(argument & MSIX_ENABLE) && !epc_features->msi_capable)) {
- ctrl->command_status = COMMAND_STATUS_ERROR;
+ if (((argument & EPF_NTB_MSIX_ENABLE) &&
+ !epc_features->msix_capable) ||
+ (!(argument & EPF_NTB_MSIX_ENABLE) &&
+ !epc_features->msi_capable)) {
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_ERROR;
break;
}
- ntb->peer_msix = argument & MSIX_ENABLE;
- ctrl->command_status = COMMAND_STATUS_OK;
+ ntb->peer_msix = argument & EPF_NTB_MSIX_ENABLE;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
- case COMMAND_TEARDOWN_DOORBELL:
- ctrl->command_status = COMMAND_STATUS_OK;
+ case EPF_NTB_COMMAND_TEARDOWN_DOORBELL:
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
- case COMMAND_CONFIGURE_MW:
+ case EPF_NTB_COMMAND_CONFIGURE_MW:
ret = epf_ntb_configure_mw(ntb, argument);
if (ret < 0)
- ctrl->command_status = COMMAND_STATUS_ERROR;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_ERROR;
else
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
- case COMMAND_TEARDOWN_MW:
+ case EPF_NTB_COMMAND_TEARDOWN_MW:
epf_ntb_teardown_mw(ntb, argument);
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
- case COMMAND_LINK_UP:
+ case EPF_NTB_COMMAND_LINK_UP:
ret = epf_ntb_set_link_enabled(ntb, true);
if (ret < 0)
- ctrl->command_status = COMMAND_STATUS_ERROR;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_ERROR;
else
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
goto reset_handler;
- case COMMAND_LINK_DOWN:
+ case EPF_NTB_COMMAND_LINK_DOWN:
ret = epf_ntb_set_link_enabled(ntb, false);
if (ret < 0)
- ctrl->command_status = COMMAND_STATUS_ERROR;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_ERROR;
else
- ctrl->command_status = COMMAND_STATUS_OK;
+ ctrl->command_status = EPF_NTB_COMMAND_STATUS_OK;
break;
default:
dev_err(dev, "UNKNOWN command: %d\n", command);
@@ -518,6 +466,28 @@ static void epf_ntb_config_spad_bar_free(struct epf_ntb *ntb)
* region
* @ntb: NTB device that facilitates communication between HOST and VHOST
*
+ * +--------------------------------------------------+ Base
+ * | |
+ * | |
+ * | |
+ * | Common Control Register |
+ * | |
+ * | |
+ * | |
+ * +-----------------------+--------------------------+ Base+spad_offset
+ * | | |
+ * | Peer Spad Space | Spad Space |
+ * | | |
+ * | | |
+ * +-----------------------+--------------------------+ Base+spad_offset
+ * | | | +spad_count * 4
+ * | | |
+ * | Spad Space | Peer Spad Space |
+ * | | |
+ * +-----------------------+--------------------------+
+ * Virtual PCI PCIe Endpoint
+ * NTB Driver NTB Driver
+ *
* Allocate the Local Memory mentioned in the above diagram. The size of
* CONFIG REGION is sizeof(struct epf_ntb_ctrl), plus space for the MSI-X
* Table and PBA if supported. The size of SCRATCHPAD REGION is obtained
@@ -602,9 +572,10 @@ static int epf_ntb_configure_interrupt(struct epf_ntb *ntb)
return -EINVAL;
}

- if (ntb->db_count < MIN_DB_COUNT || ntb->db_count > MAX_DB_COUNT) {
+ if (ntb->db_count < MIN_DB_COUNT ||
+ ntb->db_count > EPF_NTB_MAX_DB_COUNT) {
dev_err(dev, "DB count %d out of range (%d - %d)\n",
- ntb->db_count, MIN_DB_COUNT, MAX_DB_COUNT);
+ ntb->db_count, MIN_DB_COUNT, EPF_NTB_MAX_DB_COUNT);
return -EINVAL;
}

@@ -1258,7 +1229,7 @@ static ssize_t epf_ntb_db_count_store(struct config_item *item,
if (ret)
return ret;

- if (val < MIN_DB_COUNT || val > MAX_DB_COUNT)
+ if (val < MIN_DB_COUNT || val > EPF_NTB_MAX_DB_COUNT)
return -EINVAL;

WRITE_ONCE(ntb->db_count, val);
@@ -1456,7 +1427,7 @@ static int vntb_epf_db_vector_count(struct ntb_dev *ntb)
*
* Report only usable per-vector doorbell interrupts.
*/
- if (db_count < MIN_DB_COUNT || db_count > MAX_DB_COUNT)
+ if (db_count < MIN_DB_COUNT || db_count > EPF_NTB_MAX_DB_COUNT)
return 0;

return db_count - EPF_IRQ_DB_START;
diff --git a/include/linux/pci-epf-ntb.h b/include/linux/pci-epf-ntb.h
new file mode 100644
index 000000000000..0c02d709aa08
--- /dev/null
+++ b/include/linux/pci-epf-ntb.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Control region layout shared by the PCI endpoint NTB function drivers
+ * (pci-epf-ntb, pci-epf-vntb) and the host side ntb_hw_epf driver.
+ */
+
+#ifndef __LINUX_PCI_EPF_NTB_H
+#define __LINUX_PCI_EPF_NTB_H
+
+#include <linux/bits.h>
+#include <linux/types.h>
+
+#define EPF_NTB_COMMAND_CONFIGURE_DOORBELL 1
+#define EPF_NTB_COMMAND_TEARDOWN_DOORBELL 2
+#define EPF_NTB_COMMAND_CONFIGURE_MW 3
+#define EPF_NTB_COMMAND_TEARDOWN_MW 4
+#define EPF_NTB_COMMAND_LINK_UP 5
+#define EPF_NTB_COMMAND_LINK_DOWN 6
+
+/* EPF_NTB_COMMAND_CONFIGURE_DOORBELL argument */
+#define EPF_NTB_DB_COUNT_MASK GENMASK(15, 0)
+#define EPF_NTB_MSIX_ENABLE BIT(16)
+
+#define EPF_NTB_COMMAND_STATUS_OK 1
+#define EPF_NTB_COMMAND_STATUS_ERROR 2
+
+#define EPF_NTB_LINK_STATUS_UP BIT(0)
+
+#define EPF_NTB_MAX_DB_COUNT 32
+
+struct epf_ntb_ctrl {
+ u32 command;
+ u32 argument;
+ u16 command_status;
+ u16 link_status;
+ u32 topology;
+ u64 addr;
+ u64 size;
+ u32 num_mws;
+ u32 mw1_offset;
+ u32 spad_offset;
+ u32 spad_count;
+ u32 db_entry_size;
+ u32 db_data[EPF_NTB_MAX_DB_COUNT];
+ u32 db_offset[EPF_NTB_MAX_DB_COUNT];
+} __packed;
+
+#endif /* __LINUX_PCI_EPF_NTB_H */
--
2.54.0