* [PATCH 01/10] PCI: endpoint: pci-epf-vntb: Document legacy MSI doorbell offset
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 20:34 ` Frank Li
2026-02-24 13:34 ` [PATCH 02/10] PCI: endpoint: pci-epf-vntb: Defer pci_epc_raise_irq() out of atomic context Koichiro Den
` (8 subsequent siblings)
9 siblings, 1 reply; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
vntb_epf_peer_db_set() raises an MSI interrupt to notify the RC side of
a doorbell event. pci_epc_raise_irq(..., PCI_IRQ_MSI, interrupt_num)
takes a 1-based MSI interrupt number.
The ntb_hw_epf driver reserves MSI #1 for link events, so doorbells
would naturally start at MSI #2 (doorbell bit 0 -> MSI #2). However,
pci-epf-vntb has historically applied an extra offset and maps doorbell
bit 0 to MSI #3. This matches the legacy behavior of ntb_hw_epf and has
been preserved since commit e35f56bb0330 ("PCI: endpoint: Support NTB
transfer between RC and EP").
This offset has not surfaced as a functional issue because:
- ntb_hw_epf typically allocates enough MSI vectors, so the off-by-one
still hits a valid MSI vector, and
- ntb_hw_epf does not implement .db_vector_count()/.db_vector_mask(), so
client drivers such as ntb_transport effectively ignore the vector
number and schedule all QPs.
Correcting the MSI number would break interoperability with peers
running older kernels.
Document the legacy offset to avoid confusion when enabling
per-db-vector handling.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/pci/endpoint/functions/pci-epf-vntb.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
index 20a400e83439..4328f05acfe6 100644
--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
@@ -1375,6 +1375,25 @@ static int vntb_epf_peer_db_set(struct ntb_dev *ndev, u64 db_bits)
func_no = ntb->epf->func_no;
vfunc_no = ntb->epf->vfunc_no;
+ /*
+ * pci_epc_raise_irq() for MSI expects a 1-based interrupt number.
+ * ffs() returns a 1-based index (bit 0 -> 1). interrupt_num has already
+ * been computed as ffs(db_bits) + 1 above. Adding one more +1 when
+ * calling pci_epc_raise_irq() therefore results in:
+ *
+ * doorbell bit 0 -> MSI #3
+ *
+ * Legacy mapping (kept for compatibility):
+ *
+ * MSI #1 : link event (reserved)
+ * MSI #2 : unused (historical offset)
+ * MSI #3 : doorbell bit 0 (DB#0)
+ * MSI #4 : doorbell bit 1 (DB#1)
+ * ...
+ *
+ * Do not change this mapping to avoid breaking interoperability with
+ * older peers.
+ */
ret = pci_epc_raise_irq(ntb->epf->epc, func_no, vfunc_no,
PCI_IRQ_MSI, interrupt_num + 1);
if (ret)
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 01/10] PCI: endpoint: pci-epf-vntb: Document legacy MSI doorbell offset
2026-02-24 13:34 ` [PATCH 01/10] PCI: endpoint: pci-epf-vntb: Document legacy MSI doorbell offset Koichiro Den
@ 2026-02-25 20:34 ` Frank Li
0 siblings, 0 replies; 32+ messages in thread
From: Frank Li @ 2026-02-25 20:34 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:50PM +0900, Koichiro Den wrote:
> vntb_epf_peer_db_set() raises an MSI interrupt to notify the RC side of
> a doorbell event. pci_epc_raise_irq(..., PCI_IRQ_MSI, interrupt_num)
> takes a 1-based MSI interrupt number.
>
> The ntb_hw_epf driver reserves MSI #1 for link events, so doorbells
> would naturally start at MSI #2 (doorbell bit 0 -> MSI #2). However,
> pci-epf-vntb has historically applied an extra offset and maps doorbell
> bit 0 to MSI #3. This matches the legacy behavior of ntb_hw_epf and has
> been preserved since commit e35f56bb0330 ("PCI: endpoint: Support NTB
> transfer between RC and EP").
>
> This offset has not surfaced as a functional issue because:
> - ntb_hw_epf typically allocates enough MSI vectors, so the off-by-one
> still hits a valid MSI vector, and
> - ntb_hw_epf does not implement .db_vector_count()/.db_vector_mask(), so
> client drivers such as ntb_transport effectively ignore the vector
> number and schedule all QPs.
>
> Correcting the MSI number would break interoperability with peers
> running older kernels.
>
> Document the legacy offset to avoid confusion when enabling
> per-db-vector handling.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Thanks,
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/pci/endpoint/functions/pci-epf-vntb.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> index 20a400e83439..4328f05acfe6 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> @@ -1375,6 +1375,25 @@ static int vntb_epf_peer_db_set(struct ntb_dev *ndev, u64 db_bits)
> func_no = ntb->epf->func_no;
> vfunc_no = ntb->epf->vfunc_no;
>
> + /*
> + * pci_epc_raise_irq() for MSI expects a 1-based interrupt number.
> + * ffs() returns a 1-based index (bit 0 -> 1). interrupt_num has already
> + * been computed as ffs(db_bits) + 1 above. Adding one more +1 when
> + * calling pci_epc_raise_irq() therefore results in:
> + *
> + * doorbell bit 0 -> MSI #3
> + *
> + * Legacy mapping (kept for compatibility):
> + *
> + * MSI #1 : link event (reserved)
> + * MSI #2 : unused (historical offset)
> + * MSI #3 : doorbell bit 0 (DB#0)
> + * MSI #4 : doorbell bit 1 (DB#1)
> + * ...
> + *
> + * Do not change this mapping to avoid breaking interoperability with
> + * older peers.
> + */
> ret = pci_epc_raise_irq(ntb->epf->epc, func_no, vfunc_no,
> PCI_IRQ_MSI, interrupt_num + 1);
> if (ret)
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 02/10] PCI: endpoint: pci-epf-vntb: Defer pci_epc_raise_irq() out of atomic context
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
2026-02-24 13:34 ` [PATCH 01/10] PCI: endpoint: pci-epf-vntb: Document legacy MSI doorbell offset Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 20:36 ` Frank Li
2026-02-27 7:32 ` Koichiro Den
2026-02-24 13:34 ` [PATCH 03/10] PCI: endpoint: pci-epf-vntb: Report 0-based doorbell vector via ntb_db_event() Koichiro Den
` (7 subsequent siblings)
9 siblings, 2 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
The NTB .peer_db_set() callback may be invoked from atomic context.
pci-epf-vntb currently calls pci_epc_raise_irq() directly, but
pci_epc_raise_irq() may sleep (it takes epc->lock).
Avoid sleeping in atomic context by coalescing doorbell bits into an
atomic64 pending mask and raising MSIs from a work item. Limit the
amount of work per run to avoid monopolizing the workqueue under a
doorbell storm.
Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP")
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/pci/endpoint/functions/pci-epf-vntb.c | 109 +++++++++++++-----
1 file changed, 81 insertions(+), 28 deletions(-)
diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
index 4328f05acfe6..c00898ac8269 100644
--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
@@ -69,6 +69,9 @@ static struct workqueue_struct *kpcintb_workqueue;
#define MAX_DB_COUNT 32
#define MAX_MW 4
+/* Limit per-work execution to avoid monopolizing kworker on doorbell storms. */
+#define VNTB_PEER_DB_WORK_BUDGET 5
+
enum epf_ntb_bar {
BAR_CONFIG,
BAR_DB,
@@ -129,6 +132,8 @@ struct epf_ntb {
u32 spad_count;
u64 mws_size[MAX_MW];
atomic64_t db;
+ atomic64_t peer_db_pending;
+ struct work_struct peer_db_work;
u32 vbus_number;
u16 vntb_pid;
u16 vntb_vid;
@@ -933,6 +938,8 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb)
INIT_DELAYED_WORK(&ntb->cmd_handler, epf_ntb_cmd_handler);
queue_work(kpcintb_workqueue, &ntb->cmd_handler.work);
+ enable_work(&ntb->peer_db_work);
+
return 0;
err_write_header:
@@ -955,6 +962,7 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb)
*/
static void epf_ntb_epc_cleanup(struct epf_ntb *ntb)
{
+ disable_work_sync(&ntb->peer_db_work);
epf_ntb_mw_bar_clear(ntb, ntb->num_mws);
epf_ntb_db_bar_clear(ntb);
epf_ntb_config_sspad_bar_clear(ntb);
@@ -1365,41 +1373,82 @@ static int vntb_epf_peer_spad_write(struct ntb_dev *ndev, int pidx, int idx, u32
return 0;
}
+static void vntb_epf_peer_db_work(struct work_struct *work)
+{
+ struct epf_ntb *ntb = container_of(work, struct epf_ntb, peer_db_work);
+ struct pci_epf *epf = ntb->epf;
+ unsigned int budget = VNTB_PEER_DB_WORK_BUDGET;
+ u8 func_no, vfunc_no;
+ u32 interrupt_num;
+ u64 db_bits;
+ int ret;
+
+ if (!epf || !epf->epc)
+ return;
+
+ func_no = epf->func_no;
+ vfunc_no = epf->vfunc_no;
+
+ /*
+ * Drain doorbells from peer_db_pending in snapshots (atomic64_xchg()).
+ * Limit the number of snapshots handled per run so we don't monopolize
+ * the workqueue under a doorbell storm.
+ */
+ while (budget--) {
+ db_bits = atomic64_xchg(&ntb->peer_db_pending, 0);
+ if (!db_bits)
+ return;
+
+ while (db_bits) {
+ /*
+ * pci_epc_raise_irq() for MSI expects a 1-based
+ * interrupt number. ffs() returns a 1-based index (bit
+ * 0 -> 1). interrupt_num has already been computed as
+ * ffs(db_bits) + 1 above. Adding one more +1 when
+ * calling pci_epc_raise_irq() therefore results in:
+ *
+ * doorbell bit 0 -> MSI #3
+ *
+ * Legacy mapping (kept for compatibility):
+ *
+ * MSI #1 : link event (reserved)
+ * MSI #2 : unused (historical offset)
+ * MSI #3 : doorbell bit 0 (DB#0)
+ * MSI #4 : doorbell bit 1 (DB#1)
+ * ...
+ *
+ * Do not change this mapping to avoid breaking
+ * interoperability with older peers.
+ */
+ interrupt_num = ffs(db_bits) + 2;
+ db_bits &= db_bits - 1;
+
+ ret = pci_epc_raise_irq(epf->epc, func_no, vfunc_no,
+ PCI_IRQ_MSI, interrupt_num);
+ if (ret)
+ dev_err(&ntb->ntb.dev,
+ "Failed to raise IRQ for interrupt_num %u: %d\n",
+ interrupt_num, ret);
+ }
+ }
+
+ if (atomic64_read(&ntb->peer_db_pending))
+ queue_work(kpcintb_workqueue, &ntb->peer_db_work);
+}
+
static int vntb_epf_peer_db_set(struct ntb_dev *ndev, u64 db_bits)
{
- u32 interrupt_num = ffs(db_bits) + 1;
struct epf_ntb *ntb = ntb_ndev(ndev);
- u8 func_no, vfunc_no;
- int ret;
-
- func_no = ntb->epf->func_no;
- vfunc_no = ntb->epf->vfunc_no;
/*
- * pci_epc_raise_irq() for MSI expects a 1-based interrupt number.
- * ffs() returns a 1-based index (bit 0 -> 1). interrupt_num has already
- * been computed as ffs(db_bits) + 1 above. Adding one more +1 when
- * calling pci_epc_raise_irq() therefore results in:
- *
- * doorbell bit 0 -> MSI #3
- *
- * Legacy mapping (kept for compatibility):
- *
- * MSI #1 : link event (reserved)
- * MSI #2 : unused (historical offset)
- * MSI #3 : doorbell bit 0 (DB#0)
- * MSI #4 : doorbell bit 1 (DB#1)
- * ...
- *
- * Do not change this mapping to avoid breaking interoperability with
- * older peers.
+ * .peer_db_set() may be called from atomic context. pci_epc_raise_irq()
+ * can sleep (it takes epc->lock), so defer MSI raising to process
+ * context. Doorbell requests are coalesced in peer_db_pending.
*/
- ret = pci_epc_raise_irq(ntb->epf->epc, func_no, vfunc_no,
- PCI_IRQ_MSI, interrupt_num + 1);
- if (ret)
- dev_err(&ntb->ntb.dev, "Failed to raise IRQ\n");
+ atomic64_or(db_bits, &ntb->peer_db_pending);
+ queue_work(kpcintb_workqueue, &ntb->peer_db_work);
- return ret;
+ return 0;
}
static u64 vntb_epf_db_read(struct ntb_dev *ndev)
@@ -1641,6 +1690,10 @@ static int epf_ntb_probe(struct pci_epf *epf,
ntb->epf = epf;
ntb->vbus_number = 0xff;
+ INIT_WORK(&ntb->peer_db_work, vntb_epf_peer_db_work);
+ disable_work(&ntb->peer_db_work);
+ atomic64_set(&ntb->peer_db_pending, 0);
+
/* Initially, no bar is assigned */
for (i = 0; i < VNTB_BAR_NUM; i++)
ntb->epf_ntb_bar[i] = NO_BAR;
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 02/10] PCI: endpoint: pci-epf-vntb: Defer pci_epc_raise_irq() out of atomic context
2026-02-24 13:34 ` [PATCH 02/10] PCI: endpoint: pci-epf-vntb: Defer pci_epc_raise_irq() out of atomic context Koichiro Den
@ 2026-02-25 20:36 ` Frank Li
2026-02-26 1:02 ` Koichiro Den
2026-02-27 7:32 ` Koichiro Den
1 sibling, 1 reply; 32+ messages in thread
From: Frank Li @ 2026-02-25 20:36 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:51PM +0900, Koichiro Den wrote:
> The NTB .peer_db_set() callback may be invoked from atomic context.
> pci-epf-vntb currently calls pci_epc_raise_irq() directly, but
> pci_epc_raise_irq() may sleep (it takes epc->lock).
Can we use thread irq handle()?
Frank
>
> Avoid sleeping in atomic context by coalescing doorbell bits into an
> atomic64 pending mask and raising MSIs from a work item. Limit the
> amount of work per run to avoid monopolizing the workqueue under a
> doorbell storm.
>
> Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/pci/endpoint/functions/pci-epf-vntb.c | 109 +++++++++++++-----
> 1 file changed, 81 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> index 4328f05acfe6..c00898ac8269 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> @@ -69,6 +69,9 @@ static struct workqueue_struct *kpcintb_workqueue;
> #define MAX_DB_COUNT 32
> #define MAX_MW 4
>
> +/* Limit per-work execution to avoid monopolizing kworker on doorbell storms. */
> +#define VNTB_PEER_DB_WORK_BUDGET 5
> +
> enum epf_ntb_bar {
> BAR_CONFIG,
> BAR_DB,
> @@ -129,6 +132,8 @@ struct epf_ntb {
> u32 spad_count;
> u64 mws_size[MAX_MW];
> atomic64_t db;
> + atomic64_t peer_db_pending;
> + struct work_struct peer_db_work;
> u32 vbus_number;
> u16 vntb_pid;
> u16 vntb_vid;
> @@ -933,6 +938,8 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb)
> INIT_DELAYED_WORK(&ntb->cmd_handler, epf_ntb_cmd_handler);
> queue_work(kpcintb_workqueue, &ntb->cmd_handler.work);
>
> + enable_work(&ntb->peer_db_work);
> +
> return 0;
>
> err_write_header:
> @@ -955,6 +962,7 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb)
> */
> static void epf_ntb_epc_cleanup(struct epf_ntb *ntb)
> {
> + disable_work_sync(&ntb->peer_db_work);
> epf_ntb_mw_bar_clear(ntb, ntb->num_mws);
> epf_ntb_db_bar_clear(ntb);
> epf_ntb_config_sspad_bar_clear(ntb);
> @@ -1365,41 +1373,82 @@ static int vntb_epf_peer_spad_write(struct ntb_dev *ndev, int pidx, int idx, u32
> return 0;
> }
>
> +static void vntb_epf_peer_db_work(struct work_struct *work)
> +{
> + struct epf_ntb *ntb = container_of(work, struct epf_ntb, peer_db_work);
> + struct pci_epf *epf = ntb->epf;
> + unsigned int budget = VNTB_PEER_DB_WORK_BUDGET;
> + u8 func_no, vfunc_no;
> + u32 interrupt_num;
> + u64 db_bits;
> + int ret;
> +
> + if (!epf || !epf->epc)
> + return;
> +
> + func_no = epf->func_no;
> + vfunc_no = epf->vfunc_no;
> +
> + /*
> + * Drain doorbells from peer_db_pending in snapshots (atomic64_xchg()).
> + * Limit the number of snapshots handled per run so we don't monopolize
> + * the workqueue under a doorbell storm.
> + */
> + while (budget--) {
> + db_bits = atomic64_xchg(&ntb->peer_db_pending, 0);
> + if (!db_bits)
> + return;
> +
> + while (db_bits) {
> + /*
> + * pci_epc_raise_irq() for MSI expects a 1-based
> + * interrupt number. ffs() returns a 1-based index (bit
> + * 0 -> 1). interrupt_num has already been computed as
> + * ffs(db_bits) + 1 above. Adding one more +1 when
> + * calling pci_epc_raise_irq() therefore results in:
> + *
> + * doorbell bit 0 -> MSI #3
> + *
> + * Legacy mapping (kept for compatibility):
> + *
> + * MSI #1 : link event (reserved)
> + * MSI #2 : unused (historical offset)
> + * MSI #3 : doorbell bit 0 (DB#0)
> + * MSI #4 : doorbell bit 1 (DB#1)
> + * ...
> + *
> + * Do not change this mapping to avoid breaking
> + * interoperability with older peers.
> + */
> + interrupt_num = ffs(db_bits) + 2;
> + db_bits &= db_bits - 1;
> +
> + ret = pci_epc_raise_irq(epf->epc, func_no, vfunc_no,
> + PCI_IRQ_MSI, interrupt_num);
> + if (ret)
> + dev_err(&ntb->ntb.dev,
> + "Failed to raise IRQ for interrupt_num %u: %d\n",
> + interrupt_num, ret);
> + }
> + }
> +
> + if (atomic64_read(&ntb->peer_db_pending))
> + queue_work(kpcintb_workqueue, &ntb->peer_db_work);
> +}
> +
> static int vntb_epf_peer_db_set(struct ntb_dev *ndev, u64 db_bits)
> {
> - u32 interrupt_num = ffs(db_bits) + 1;
> struct epf_ntb *ntb = ntb_ndev(ndev);
> - u8 func_no, vfunc_no;
> - int ret;
> -
> - func_no = ntb->epf->func_no;
> - vfunc_no = ntb->epf->vfunc_no;
>
> /*
> - * pci_epc_raise_irq() for MSI expects a 1-based interrupt number.
> - * ffs() returns a 1-based index (bit 0 -> 1). interrupt_num has already
> - * been computed as ffs(db_bits) + 1 above. Adding one more +1 when
> - * calling pci_epc_raise_irq() therefore results in:
> - *
> - * doorbell bit 0 -> MSI #3
> - *
> - * Legacy mapping (kept for compatibility):
> - *
> - * MSI #1 : link event (reserved)
> - * MSI #2 : unused (historical offset)
> - * MSI #3 : doorbell bit 0 (DB#0)
> - * MSI #4 : doorbell bit 1 (DB#1)
> - * ...
> - *
> - * Do not change this mapping to avoid breaking interoperability with
> - * older peers.
> + * .peer_db_set() may be called from atomic context. pci_epc_raise_irq()
> + * can sleep (it takes epc->lock), so defer MSI raising to process
> + * context. Doorbell requests are coalesced in peer_db_pending.
> */
> - ret = pci_epc_raise_irq(ntb->epf->epc, func_no, vfunc_no,
> - PCI_IRQ_MSI, interrupt_num + 1);
> - if (ret)
> - dev_err(&ntb->ntb.dev, "Failed to raise IRQ\n");
> + atomic64_or(db_bits, &ntb->peer_db_pending);
> + queue_work(kpcintb_workqueue, &ntb->peer_db_work);
>
> - return ret;
> + return 0;
> }
>
> static u64 vntb_epf_db_read(struct ntb_dev *ndev)
> @@ -1641,6 +1690,10 @@ static int epf_ntb_probe(struct pci_epf *epf,
> ntb->epf = epf;
> ntb->vbus_number = 0xff;
>
> + INIT_WORK(&ntb->peer_db_work, vntb_epf_peer_db_work);
> + disable_work(&ntb->peer_db_work);
> + atomic64_set(&ntb->peer_db_pending, 0);
> +
> /* Initially, no bar is assigned */
> for (i = 0; i < VNTB_BAR_NUM; i++)
> ntb->epf_ntb_bar[i] = NO_BAR;
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH 02/10] PCI: endpoint: pci-epf-vntb: Defer pci_epc_raise_irq() out of atomic context
2026-02-25 20:36 ` Frank Li
@ 2026-02-26 1:02 ` Koichiro Den
0 siblings, 0 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-26 1:02 UTC (permalink / raw)
To: Frank Li
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Wed, Feb 25, 2026 at 03:36:05PM -0500, Frank Li wrote:
> On Tue, Feb 24, 2026 at 10:34:51PM +0900, Koichiro Den wrote:
> > The NTB .peer_db_set() callback may be invoked from atomic context.
> > pci-epf-vntb currently calls pci_epc_raise_irq() directly, but
> > pci_epc_raise_irq() may sleep (it takes epc->lock).
>
> Can we use thread irq handle()?
I don't think so. ntb_peer_db_set() can be invoked from softirq context.
Thanks for the review,
Koichiro
>
> Frank
> >
> > Avoid sleeping in atomic context by coalescing doorbell bits into an
> > atomic64 pending mask and raising MSIs from a work item. Limit the
> > amount of work per run to avoid monopolizing the workqueue under a
> > doorbell storm.
> >
> > Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP")
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> > drivers/pci/endpoint/functions/pci-epf-vntb.c | 109 +++++++++++++-----
> > 1 file changed, 81 insertions(+), 28 deletions(-)
> >
> > diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> > index 4328f05acfe6..c00898ac8269 100644
> > --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
> > +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> > @@ -69,6 +69,9 @@ static struct workqueue_struct *kpcintb_workqueue;
> > #define MAX_DB_COUNT 32
> > #define MAX_MW 4
> >
> > +/* Limit per-work execution to avoid monopolizing kworker on doorbell storms. */
> > +#define VNTB_PEER_DB_WORK_BUDGET 5
> > +
> > enum epf_ntb_bar {
> > BAR_CONFIG,
> > BAR_DB,
> > @@ -129,6 +132,8 @@ struct epf_ntb {
> > u32 spad_count;
> > u64 mws_size[MAX_MW];
> > atomic64_t db;
> > + atomic64_t peer_db_pending;
> > + struct work_struct peer_db_work;
> > u32 vbus_number;
> > u16 vntb_pid;
> > u16 vntb_vid;
> > @@ -933,6 +938,8 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb)
> > INIT_DELAYED_WORK(&ntb->cmd_handler, epf_ntb_cmd_handler);
> > queue_work(kpcintb_workqueue, &ntb->cmd_handler.work);
> >
> > + enable_work(&ntb->peer_db_work);
> > +
> > return 0;
> >
> > err_write_header:
> > @@ -955,6 +962,7 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb)
> > */
> > static void epf_ntb_epc_cleanup(struct epf_ntb *ntb)
> > {
> > + disable_work_sync(&ntb->peer_db_work);
> > epf_ntb_mw_bar_clear(ntb, ntb->num_mws);
> > epf_ntb_db_bar_clear(ntb);
> > epf_ntb_config_sspad_bar_clear(ntb);
> > @@ -1365,41 +1373,82 @@ static int vntb_epf_peer_spad_write(struct ntb_dev *ndev, int pidx, int idx, u32
> > return 0;
> > }
> >
> > +static void vntb_epf_peer_db_work(struct work_struct *work)
> > +{
> > + struct epf_ntb *ntb = container_of(work, struct epf_ntb, peer_db_work);
> > + struct pci_epf *epf = ntb->epf;
> > + unsigned int budget = VNTB_PEER_DB_WORK_BUDGET;
> > + u8 func_no, vfunc_no;
> > + u32 interrupt_num;
> > + u64 db_bits;
> > + int ret;
> > +
> > + if (!epf || !epf->epc)
> > + return;
> > +
> > + func_no = epf->func_no;
> > + vfunc_no = epf->vfunc_no;
> > +
> > + /*
> > + * Drain doorbells from peer_db_pending in snapshots (atomic64_xchg()).
> > + * Limit the number of snapshots handled per run so we don't monopolize
> > + * the workqueue under a doorbell storm.
> > + */
> > + while (budget--) {
> > + db_bits = atomic64_xchg(&ntb->peer_db_pending, 0);
> > + if (!db_bits)
> > + return;
> > +
> > + while (db_bits) {
> > + /*
> > + * pci_epc_raise_irq() for MSI expects a 1-based
> > + * interrupt number. ffs() returns a 1-based index (bit
> > + * 0 -> 1). interrupt_num has already been computed as
> > + * ffs(db_bits) + 1 above. Adding one more +1 when
> > + * calling pci_epc_raise_irq() therefore results in:
> > + *
> > + * doorbell bit 0 -> MSI #3
> > + *
> > + * Legacy mapping (kept for compatibility):
> > + *
> > + * MSI #1 : link event (reserved)
> > + * MSI #2 : unused (historical offset)
> > + * MSI #3 : doorbell bit 0 (DB#0)
> > + * MSI #4 : doorbell bit 1 (DB#1)
> > + * ...
> > + *
> > + * Do not change this mapping to avoid breaking
> > + * interoperability with older peers.
> > + */
> > + interrupt_num = ffs(db_bits) + 2;
> > + db_bits &= db_bits - 1;
> > +
> > + ret = pci_epc_raise_irq(epf->epc, func_no, vfunc_no,
> > + PCI_IRQ_MSI, interrupt_num);
> > + if (ret)
> > + dev_err(&ntb->ntb.dev,
> > + "Failed to raise IRQ for interrupt_num %u: %d\n",
> > + interrupt_num, ret);
> > + }
> > + }
> > +
> > + if (atomic64_read(&ntb->peer_db_pending))
> > + queue_work(kpcintb_workqueue, &ntb->peer_db_work);
> > +}
> > +
> > static int vntb_epf_peer_db_set(struct ntb_dev *ndev, u64 db_bits)
> > {
> > - u32 interrupt_num = ffs(db_bits) + 1;
> > struct epf_ntb *ntb = ntb_ndev(ndev);
> > - u8 func_no, vfunc_no;
> > - int ret;
> > -
> > - func_no = ntb->epf->func_no;
> > - vfunc_no = ntb->epf->vfunc_no;
> >
> > /*
> > - * pci_epc_raise_irq() for MSI expects a 1-based interrupt number.
> > - * ffs() returns a 1-based index (bit 0 -> 1). interrupt_num has already
> > - * been computed as ffs(db_bits) + 1 above. Adding one more +1 when
> > - * calling pci_epc_raise_irq() therefore results in:
> > - *
> > - * doorbell bit 0 -> MSI #3
> > - *
> > - * Legacy mapping (kept for compatibility):
> > - *
> > - * MSI #1 : link event (reserved)
> > - * MSI #2 : unused (historical offset)
> > - * MSI #3 : doorbell bit 0 (DB#0)
> > - * MSI #4 : doorbell bit 1 (DB#1)
> > - * ...
> > - *
> > - * Do not change this mapping to avoid breaking interoperability with
> > - * older peers.
> > + * .peer_db_set() may be called from atomic context. pci_epc_raise_irq()
> > + * can sleep (it takes epc->lock), so defer MSI raising to process
> > + * context. Doorbell requests are coalesced in peer_db_pending.
> > */
> > - ret = pci_epc_raise_irq(ntb->epf->epc, func_no, vfunc_no,
> > - PCI_IRQ_MSI, interrupt_num + 1);
> > - if (ret)
> > - dev_err(&ntb->ntb.dev, "Failed to raise IRQ\n");
> > + atomic64_or(db_bits, &ntb->peer_db_pending);
> > + queue_work(kpcintb_workqueue, &ntb->peer_db_work);
> >
> > - return ret;
> > + return 0;
> > }
> >
> > static u64 vntb_epf_db_read(struct ntb_dev *ndev)
> > @@ -1641,6 +1690,10 @@ static int epf_ntb_probe(struct pci_epf *epf,
> > ntb->epf = epf;
> > ntb->vbus_number = 0xff;
> >
> > + INIT_WORK(&ntb->peer_db_work, vntb_epf_peer_db_work);
> > + disable_work(&ntb->peer_db_work);
> > + atomic64_set(&ntb->peer_db_pending, 0);
> > +
> > /* Initially, no bar is assigned */
> > for (i = 0; i < VNTB_BAR_NUM; i++)
> > ntb->epf_ntb_bar[i] = NO_BAR;
> > --
> > 2.51.0
> >
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 02/10] PCI: endpoint: pci-epf-vntb: Defer pci_epc_raise_irq() out of atomic context
2026-02-24 13:34 ` [PATCH 02/10] PCI: endpoint: pci-epf-vntb: Defer pci_epc_raise_irq() out of atomic context Koichiro Den
2026-02-25 20:36 ` Frank Li
@ 2026-02-27 7:32 ` Koichiro Den
1 sibling, 0 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-27 7:32 UTC (permalink / raw)
To: Frank.Li, dave.jiang
Cc: kishon, jdmason, mani, allenbh, kwilczynski, bhelgaas, jbrunet,
lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:51PM +0900, Koichiro Den wrote:
> The NTB .peer_db_set() callback may be invoked from atomic context.
> pci-epf-vntb currently calls pci_epc_raise_irq() directly, but
> pci_epc_raise_irq() may sleep (it takes epc->lock).
>
> Avoid sleeping in atomic context by coalescing doorbell bits into an
> atomic64 pending mask and raising MSIs from a work item. Limit the
> amount of work per run to avoid monopolizing the workqueue under a
> doorbell storm.
>
> Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/pci/endpoint/functions/pci-epf-vntb.c | 109 +++++++++++++-----
> 1 file changed, 81 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> index 4328f05acfe6..c00898ac8269 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> @@ -69,6 +69,9 @@ static struct workqueue_struct *kpcintb_workqueue;
> #define MAX_DB_COUNT 32
> #define MAX_MW 4
>
> +/* Limit per-work execution to avoid monopolizing kworker on doorbell storms. */
> +#define VNTB_PEER_DB_WORK_BUDGET 5
> +
> enum epf_ntb_bar {
> BAR_CONFIG,
> BAR_DB,
> @@ -129,6 +132,8 @@ struct epf_ntb {
> u32 spad_count;
> u64 mws_size[MAX_MW];
> atomic64_t db;
> + atomic64_t peer_db_pending;
> + struct work_struct peer_db_work;
> u32 vbus_number;
> u16 vntb_pid;
> u16 vntb_vid;
> @@ -933,6 +938,8 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb)
> INIT_DELAYED_WORK(&ntb->cmd_handler, epf_ntb_cmd_handler);
> queue_work(kpcintb_workqueue, &ntb->cmd_handler.work);
>
> + enable_work(&ntb->peer_db_work);
> +
> return 0;
>
> err_write_header:
> @@ -955,6 +962,7 @@ static int epf_ntb_epc_init(struct epf_ntb *ntb)
> */
> static void epf_ntb_epc_cleanup(struct epf_ntb *ntb)
> {
> + disable_work_sync(&ntb->peer_db_work);
> epf_ntb_mw_bar_clear(ntb, ntb->num_mws);
> epf_ntb_db_bar_clear(ntb);
> epf_ntb_config_sspad_bar_clear(ntb);
> @@ -1365,41 +1373,82 @@ static int vntb_epf_peer_spad_write(struct ntb_dev *ndev, int pidx, int idx, u32
> return 0;
> }
>
> +static void vntb_epf_peer_db_work(struct work_struct *work)
> +{
> + struct epf_ntb *ntb = container_of(work, struct epf_ntb, peer_db_work);
> + struct pci_epf *epf = ntb->epf;
> + unsigned int budget = VNTB_PEER_DB_WORK_BUDGET;
> + u8 func_no, vfunc_no;
> + u32 interrupt_num;
> + u64 db_bits;
> + int ret;
> +
> + if (!epf || !epf->epc)
> + return;
> +
> + func_no = epf->func_no;
> + vfunc_no = epf->vfunc_no;
> +
> + /*
> + * Drain doorbells from peer_db_pending in snapshots (atomic64_xchg()).
> + * Limit the number of snapshots handled per run so we don't monopolize
> + * the workqueue under a doorbell storm.
> + */
> + while (budget--) {
> + db_bits = atomic64_xchg(&ntb->peer_db_pending, 0);
> + if (!db_bits)
> + return;
> +
> + while (db_bits) {
> + /*
> + * pci_epc_raise_irq() for MSI expects a 1-based
> + * interrupt number. ffs() returns a 1-based index (bit
> + * 0 -> 1). interrupt_num has already been computed as
> + * ffs(db_bits) + 1 above. Adding one more +1 when
> + * calling pci_epc_raise_irq() therefore results in:
I noticed that this kept-as-is comment from Patch #1 is stale. The code below
uses "+2" for the legacy offset, so the explanation no longer matches the
implementation. I'll update the comment in v2.
Koichiro
> + *
> + * doorbell bit 0 -> MSI #3
> + *
> + * Legacy mapping (kept for compatibility):
> + *
> + * MSI #1 : link event (reserved)
> + * MSI #2 : unused (historical offset)
> + * MSI #3 : doorbell bit 0 (DB#0)
> + * MSI #4 : doorbell bit 1 (DB#1)
> + * ...
> + *
> + * Do not change this mapping to avoid breaking
> + * interoperability with older peers.
> + */
> + interrupt_num = ffs(db_bits) + 2;
> + db_bits &= db_bits - 1;
> +
> + ret = pci_epc_raise_irq(epf->epc, func_no, vfunc_no,
> + PCI_IRQ_MSI, interrupt_num);
> + if (ret)
> + dev_err(&ntb->ntb.dev,
> + "Failed to raise IRQ for interrupt_num %u: %d\n",
> + interrupt_num, ret);
> + }
> + }
> +
> + if (atomic64_read(&ntb->peer_db_pending))
> + queue_work(kpcintb_workqueue, &ntb->peer_db_work);
> +}
> +
> static int vntb_epf_peer_db_set(struct ntb_dev *ndev, u64 db_bits)
> {
> - u32 interrupt_num = ffs(db_bits) + 1;
> struct epf_ntb *ntb = ntb_ndev(ndev);
> - u8 func_no, vfunc_no;
> - int ret;
> -
> - func_no = ntb->epf->func_no;
> - vfunc_no = ntb->epf->vfunc_no;
>
> /*
> - * pci_epc_raise_irq() for MSI expects a 1-based interrupt number.
> - * ffs() returns a 1-based index (bit 0 -> 1). interrupt_num has already
> - * been computed as ffs(db_bits) + 1 above. Adding one more +1 when
> - * calling pci_epc_raise_irq() therefore results in:
> - *
> - * doorbell bit 0 -> MSI #3
> - *
> - * Legacy mapping (kept for compatibility):
> - *
> - * MSI #1 : link event (reserved)
> - * MSI #2 : unused (historical offset)
> - * MSI #3 : doorbell bit 0 (DB#0)
> - * MSI #4 : doorbell bit 1 (DB#1)
> - * ...
> - *
> - * Do not change this mapping to avoid breaking interoperability with
> - * older peers.
> + * .peer_db_set() may be called from atomic context. pci_epc_raise_irq()
> + * can sleep (it takes epc->lock), so defer MSI raising to process
> + * context. Doorbell requests are coalesced in peer_db_pending.
> */
> - ret = pci_epc_raise_irq(ntb->epf->epc, func_no, vfunc_no,
> - PCI_IRQ_MSI, interrupt_num + 1);
> - if (ret)
> - dev_err(&ntb->ntb.dev, "Failed to raise IRQ\n");
> + atomic64_or(db_bits, &ntb->peer_db_pending);
> + queue_work(kpcintb_workqueue, &ntb->peer_db_work);
>
> - return ret;
> + return 0;
> }
>
> static u64 vntb_epf_db_read(struct ntb_dev *ndev)
> @@ -1641,6 +1690,10 @@ static int epf_ntb_probe(struct pci_epf *epf,
> ntb->epf = epf;
> ntb->vbus_number = 0xff;
>
> + INIT_WORK(&ntb->peer_db_work, vntb_epf_peer_db_work);
> + disable_work(&ntb->peer_db_work);
> + atomic64_set(&ntb->peer_db_pending, 0);
> +
> /* Initially, no bar is assigned */
> for (i = 0; i < VNTB_BAR_NUM; i++)
> ntb->epf_ntb_bar[i] = NO_BAR;
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 03/10] PCI: endpoint: pci-epf-vntb: Report 0-based doorbell vector via ntb_db_event()
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
2026-02-24 13:34 ` [PATCH 01/10] PCI: endpoint: pci-epf-vntb: Document legacy MSI doorbell offset Koichiro Den
2026-02-24 13:34 ` [PATCH 02/10] PCI: endpoint: pci-epf-vntb: Defer pci_epc_raise_irq() out of atomic context Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 20:54 ` Frank Li
2026-02-24 13:34 ` [PATCH 04/10] PCI: endpoint: pci-epf-vntb: Exclude reserved slots from db_valid_mask Koichiro Den
` (6 subsequent siblings)
9 siblings, 1 reply; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
ntb_db_event() expects the vector number to be relative to the first
doorbell vector starting at 0.
pci-epf-vntb reserves vector 0 for link events and uses higher vector
indices for doorbells. By passing the raw slot index to ntb_db_event(),
it effectively assumes that doorbell 0 maps to vector 1.
However, because the host uses a legacy slot layout and writes doorbell
0 into the third slot, doorbell 0 ultimately appears as vector 2 from
the NTB core perspective.
Adjust pci-epf-vntb to:
- skip the unused second slot, and
- report doorbells as 0-based vectors (DB#0 -> vector 0).
This change does not introduce a behavioral difference until
.db_vector_count()/.db_vector_mask() are implemented, because without
those callbacks NTB clients effectively ignore the vector number.
Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP")
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/pci/endpoint/functions/pci-epf-vntb.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
index c00898ac8269..cbce50afc4dc 100644
--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
@@ -266,10 +266,10 @@ static void epf_ntb_cmd_handler(struct work_struct *work)
ntb = container_of(work, struct epf_ntb, cmd_handler.work);
- for (i = 1; i < ntb->db_count && !ntb->msi_doorbell; i++) {
+ for (i = 2; i < ntb->db_count && !ntb->msi_doorbell; i++) {
if (ntb->epf_db[i]) {
- atomic64_or(1 << (i - 1), &ntb->db);
- ntb_db_event(&ntb->ntb, i);
+ atomic64_or(1 << (i - 2), &ntb->db);
+ ntb_db_event(&ntb->ntb, i - 2);
ntb->epf_db[i] = 0;
}
}
@@ -335,10 +335,10 @@ static irqreturn_t epf_ntb_doorbell_handler(int irq, void *data)
struct epf_ntb *ntb = data;
int i;
- for (i = 1; i < ntb->db_count; i++)
+ for (i = 2; i < ntb->db_count; i++)
if (irq == ntb->epf->db_msg[i].virq) {
- atomic64_or(1 << (i - 1), &ntb->db);
- ntb_db_event(&ntb->ntb, i);
+ atomic64_or(1 << (i - 2), &ntb->db);
+ ntb_db_event(&ntb->ntb, i - 2);
}
return IRQ_HANDLED;
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 03/10] PCI: endpoint: pci-epf-vntb: Report 0-based doorbell vector via ntb_db_event()
2026-02-24 13:34 ` [PATCH 03/10] PCI: endpoint: pci-epf-vntb: Report 0-based doorbell vector via ntb_db_event() Koichiro Den
@ 2026-02-25 20:54 ` Frank Li
0 siblings, 0 replies; 32+ messages in thread
From: Frank Li @ 2026-02-25 20:54 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:52PM +0900, Koichiro Den wrote:
> ntb_db_event() expects the vector number to be relative to the first
> doorbell vector starting at 0.
>
> pci-epf-vntb reserves vector 0 for link events and uses higher vector
> indices for doorbells. By passing the raw slot index to ntb_db_event(),
> it effectively assumes that doorbell 0 maps to vector 1.
>
> However, because the host uses a legacy slot layout and writes doorbell
> 0 into the third slot, doorbell 0 ultimately appears as vector 2 from
> the NTB core perspective.
>
> Adjust pci-epf-vntb to:
> - skip the unused second slot, and
> - report doorbells as 0-based vectors (DB#0 -> vector 0).
>
> This change does not introduce a behavioral difference until
> .db_vector_count()/.db_vector_mask() are implemented, because without
> those callbacks NTB clients effectively ignore the vector number.
>
> Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/pci/endpoint/functions/pci-epf-vntb.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> index c00898ac8269..cbce50afc4dc 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> @@ -266,10 +266,10 @@ static void epf_ntb_cmd_handler(struct work_struct *work)
>
> ntb = container_of(work, struct epf_ntb, cmd_handler.work);
>
> - for (i = 1; i < ntb->db_count && !ntb->msi_doorbell; i++) {
> + for (i = 2; i < ntb->db_count && !ntb->msi_doorbell; i++) {
> if (ntb->epf_db[i]) {
> - atomic64_or(1 << (i - 1), &ntb->db);
> - ntb_db_event(&ntb->ntb, i);
> + atomic64_or(1 << (i - 2), &ntb->db);
> + ntb_db_event(&ntb->ntb, i - 2);
> ntb->epf_db[i] = 0;
> }
> }
> @@ -335,10 +335,10 @@ static irqreturn_t epf_ntb_doorbell_handler(int irq, void *data)
> struct epf_ntb *ntb = data;
> int i;
>
> - for (i = 1; i < ntb->db_count; i++)
> + for (i = 2; i < ntb->db_count; i++)
> if (irq == ntb->epf->db_msg[i].virq) {
> - atomic64_or(1 << (i - 1), &ntb->db);
> - ntb_db_event(&ntb->ntb, i);
> + atomic64_or(1 << (i - 2), &ntb->db);
> + ntb_db_event(&ntb->ntb, i - 2);
> }
>
> return IRQ_HANDLED;
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 04/10] PCI: endpoint: pci-epf-vntb: Exclude reserved slots from db_valid_mask
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
` (2 preceding siblings ...)
2026-02-24 13:34 ` [PATCH 03/10] PCI: endpoint: pci-epf-vntb: Report 0-based doorbell vector via ntb_db_event() Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 20:55 ` Frank Li
2026-02-24 13:34 ` [PATCH 05/10] PCI: endpoint: pci-epf-vntb: Implement db_vector_count/mask for doorbells Koichiro Den
` (5 subsequent siblings)
9 siblings, 1 reply; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
In pci-epf-vntb, db_count represents the total number of doorbell slots
exposed to the peer, including:
- slot #0 reserved for link events, and
- slot #1 historically unused (kept for compatibility).
Only the remaining slots correspond to actual doorbell bits. The current
db_valid_mask() exposes all slots as valid doorbells.
Limit db_valid_mask() to the real doorbell bits by returning
BIT_ULL(db_count - 2) - 1, and guard against db_count < 2.
Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP")
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/pci/endpoint/functions/pci-epf-vntb.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
index cbce50afc4dc..2eb3db035644 100644
--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
@@ -1269,7 +1269,10 @@ static int vntb_epf_peer_mw_count(struct ntb_dev *ntb)
static u64 vntb_epf_db_valid_mask(struct ntb_dev *ntb)
{
- return BIT_ULL(ntb_ndev(ntb)->db_count) - 1;
+ if (ntb_ndev(ntb)->db_count < 2)
+ return 0;
+
+ return BIT_ULL(ntb_ndev(ntb)->db_count - 2) - 1;
}
static int vntb_epf_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 04/10] PCI: endpoint: pci-epf-vntb: Exclude reserved slots from db_valid_mask
2026-02-24 13:34 ` [PATCH 04/10] PCI: endpoint: pci-epf-vntb: Exclude reserved slots from db_valid_mask Koichiro Den
@ 2026-02-25 20:55 ` Frank Li
0 siblings, 0 replies; 32+ messages in thread
From: Frank Li @ 2026-02-25 20:55 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:53PM +0900, Koichiro Den wrote:
> In pci-epf-vntb, db_count represents the total number of doorbell slots
> exposed to the peer, including:
> - slot #0 reserved for link events, and
> - slot #1 historically unused (kept for compatibility).
>
> Only the remaining slots correspond to actual doorbell bits. The current
> db_valid_mask() exposes all slots as valid doorbells.
>
> Limit db_valid_mask() to the real doorbell bits by returning
> BIT_ULL(db_count - 2) - 1, and guard against db_count < 2.
>
> Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/pci/endpoint/functions/pci-epf-vntb.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> index cbce50afc4dc..2eb3db035644 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> @@ -1269,7 +1269,10 @@ static int vntb_epf_peer_mw_count(struct ntb_dev *ntb)
>
> static u64 vntb_epf_db_valid_mask(struct ntb_dev *ntb)
> {
> - return BIT_ULL(ntb_ndev(ntb)->db_count) - 1;
> + if (ntb_ndev(ntb)->db_count < 2)
> + return 0;
> +
> + return BIT_ULL(ntb_ndev(ntb)->db_count - 2) - 1;
> }
>
> static int vntb_epf_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 05/10] PCI: endpoint: pci-epf-vntb: Implement db_vector_count/mask for doorbells
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
` (3 preceding siblings ...)
2026-02-24 13:34 ` [PATCH 04/10] PCI: endpoint: pci-epf-vntb: Exclude reserved slots from db_valid_mask Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 21:02 ` Frank Li
2026-02-24 13:34 ` [PATCH 06/10] NTB: epf: Document legacy doorbell slot offset in ntb_epf_peer_db_set() Koichiro Den
` (4 subsequent siblings)
9 siblings, 1 reply; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
Implement .db_vector_count and .db_vector_mask so ntb core/clients can map
doorbell events to per-vector work and avoid the thundering-herd behavior.
pci-epf-vntb reserves two slots in db_count: slot 0 for link events and
slot 1 which is historically unused. Therefore the number of doorbell
vectors is (db_count - 2).
Report vectors as 0..N-1 and return BIT_ULL(db_vector) for the
corresponding doorbell bit. While at it, use vntb_epf_db_vector_mask()
to simplify vntb_epf_db_valid_mask().
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/pci/endpoint/functions/pci-epf-vntb.c | 36 +++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
index 2eb3db035644..b651c54d6bef 100644
--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
@@ -1267,12 +1267,42 @@ static int vntb_epf_peer_mw_count(struct ntb_dev *ntb)
return ntb_ndev(ntb)->num_mws;
}
+static int vntb_epf_db_vector_count(struct ntb_dev *ntb)
+{
+ struct epf_ntb *ndev = ntb_ndev(ntb);
+
+ /*
+ * ndev->db_count is the total number of doorbell slots exposed to
+ * the peer, including:
+ * - slot #0 reserved for link events
+ * - slot #1 historically unused (kept for protocol compatibility)
+ *
+ * Report only usable per-vector doorbell interrupts.
+ */
+ if (ndev->db_count < 2)
+ return 0;
+
+ return ndev->db_count - 2;
+}
+
static u64 vntb_epf_db_valid_mask(struct ntb_dev *ntb)
{
- if (ntb_ndev(ntb)->db_count < 2)
+ return BIT_ULL(vntb_epf_db_vector_count(ntb)) - 1;
+}
+
+static u64 vntb_epf_db_vector_mask(struct ntb_dev *ntb, int db_vector)
+{
+ int nr_vec;
+
+ /*
+ * Doorbell vectors are numbered [0 .. nr_vec - 1], where nr_vec
+ * excludes the two reserved slots described above.
+ */
+ nr_vec = vntb_epf_db_vector_count(ntb);
+ if (db_vector < 0 || db_vector >= nr_vec)
return 0;
- return BIT_ULL(ntb_ndev(ntb)->db_count - 2) - 1;
+ return BIT_ULL(db_vector);
}
static int vntb_epf_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
@@ -1512,6 +1542,8 @@ static const struct ntb_dev_ops vntb_epf_ops = {
.spad_count = vntb_epf_spad_count,
.peer_mw_count = vntb_epf_peer_mw_count,
.db_valid_mask = vntb_epf_db_valid_mask,
+ .db_vector_count = vntb_epf_db_vector_count,
+ .db_vector_mask = vntb_epf_db_vector_mask,
.db_set_mask = vntb_epf_db_set_mask,
.mw_set_trans = vntb_epf_mw_set_trans,
.mw_clear_trans = vntb_epf_mw_clear_trans,
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 05/10] PCI: endpoint: pci-epf-vntb: Implement db_vector_count/mask for doorbells
2026-02-24 13:34 ` [PATCH 05/10] PCI: endpoint: pci-epf-vntb: Implement db_vector_count/mask for doorbells Koichiro Den
@ 2026-02-25 21:02 ` Frank Li
2026-02-27 6:23 ` Koichiro Den
0 siblings, 1 reply; 32+ messages in thread
From: Frank Li @ 2026-02-25 21:02 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:54PM +0900, Koichiro Den wrote:
> Implement .db_vector_count and .db_vector_mask so ntb core/clients can map
> doorbell events to per-vector work and avoid the thundering-herd behavior.
>
> pci-epf-vntb reserves two slots in db_count: slot 0 for link events and
> slot 1 which is historically unused. Therefore the number of doorbell
> vectors is (db_count - 2).
>
> Report vectors as 0..N-1 and return BIT_ULL(db_vector) for the
> corresponding doorbell bit. While at it, use vntb_epf_db_vector_mask()
> to simplify vntb_epf_db_valid_mask().
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/pci/endpoint/functions/pci-epf-vntb.c | 36 +++++++++++++++++--
> 1 file changed, 34 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> index 2eb3db035644..b651c54d6bef 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> @@ -1267,12 +1267,42 @@ static int vntb_epf_peer_mw_count(struct ntb_dev *ntb)
> return ntb_ndev(ntb)->num_mws;
> }
>
> +static int vntb_epf_db_vector_count(struct ntb_dev *ntb)
> +{
> + struct epf_ntb *ndev = ntb_ndev(ntb);
> +
> + /*
> + * ndev->db_count is the total number of doorbell slots exposed to
> + * the peer, including:
> + * - slot #0 reserved for link events
> + * - slot #1 historically unused (kept for protocol compatibility)
> + *
> + * Report only usable per-vector doorbell interrupts.
> + */
> + if (ndev->db_count < 2)
> + return 0;
> +
> + return ndev->db_count - 2;
return max(ndev->db_count - 2, 0);
Frank
> +}
> +
> static u64 vntb_epf_db_valid_mask(struct ntb_dev *ntb)
> {
> - if (ntb_ndev(ntb)->db_count < 2)
> + return BIT_ULL(vntb_epf_db_vector_count(ntb)) - 1;
> +}
> +
> +static u64 vntb_epf_db_vector_mask(struct ntb_dev *ntb, int db_vector)
> +{
> + int nr_vec;
> +
> + /*
> + * Doorbell vectors are numbered [0 .. nr_vec - 1], where nr_vec
> + * excludes the two reserved slots described above.
> + */
> + nr_vec = vntb_epf_db_vector_count(ntb);
> + if (db_vector < 0 || db_vector >= nr_vec)
> return 0;
>
> - return BIT_ULL(ntb_ndev(ntb)->db_count - 2) - 1;
> + return BIT_ULL(db_vector);
> }
>
> static int vntb_epf_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
> @@ -1512,6 +1542,8 @@ static const struct ntb_dev_ops vntb_epf_ops = {
> .spad_count = vntb_epf_spad_count,
> .peer_mw_count = vntb_epf_peer_mw_count,
> .db_valid_mask = vntb_epf_db_valid_mask,
> + .db_vector_count = vntb_epf_db_vector_count,
> + .db_vector_mask = vntb_epf_db_vector_mask,
> .db_set_mask = vntb_epf_db_set_mask,
> .mw_set_trans = vntb_epf_mw_set_trans,
> .mw_clear_trans = vntb_epf_mw_clear_trans,
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH 05/10] PCI: endpoint: pci-epf-vntb: Implement db_vector_count/mask for doorbells
2026-02-25 21:02 ` Frank Li
@ 2026-02-27 6:23 ` Koichiro Den
0 siblings, 0 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-27 6:23 UTC (permalink / raw)
To: Frank Li
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Wed, Feb 25, 2026 at 04:02:01PM -0500, Frank Li wrote:
> On Tue, Feb 24, 2026 at 10:34:54PM +0900, Koichiro Den wrote:
> > Implement .db_vector_count and .db_vector_mask so ntb core/clients can map
> > doorbell events to per-vector work and avoid the thundering-herd behavior.
> >
> > pci-epf-vntb reserves two slots in db_count: slot 0 for link events and
> > slot 1 which is historically unused. Therefore the number of doorbell
> > vectors is (db_count - 2).
> >
> > Report vectors as 0..N-1 and return BIT_ULL(db_vector) for the
> > corresponding doorbell bit. While at it, use vntb_epf_db_vector_mask()
> > to simplify vntb_epf_db_valid_mask().
> >
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> > drivers/pci/endpoint/functions/pci-epf-vntb.c | 36 +++++++++++++++++--
> > 1 file changed, 34 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> > index 2eb3db035644..b651c54d6bef 100644
> > --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
> > +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> > @@ -1267,12 +1267,42 @@ static int vntb_epf_peer_mw_count(struct ntb_dev *ntb)
> > return ntb_ndev(ntb)->num_mws;
> > }
> >
> > +static int vntb_epf_db_vector_count(struct ntb_dev *ntb)
> > +{
> > + struct epf_ntb *ndev = ntb_ndev(ntb);
> > +
> > + /*
> > + * ndev->db_count is the total number of doorbell slots exposed to
> > + * the peer, including:
> > + * - slot #0 reserved for link events
> > + * - slot #1 historically unused (kept for protocol compatibility)
> > + *
> > + * Report only usable per-vector doorbell interrupts.
> > + */
> > + if (ndev->db_count < 2)
> > + return 0;
> > +
> > + return ndev->db_count - 2;
>
> return max(ndev->db_count - 2, 0);
db_count is u32, so it could underflow.
If a one-liner is preferred, something like:
max_t(u32, ndev->db_count, 2U) - 2
would work. Personally, I think the original version is clearer.
Thanks,
Koichiro
>
> Frank
> > +}
> > +
> > static u64 vntb_epf_db_valid_mask(struct ntb_dev *ntb)
> > {
> > - if (ntb_ndev(ntb)->db_count < 2)
> > + return BIT_ULL(vntb_epf_db_vector_count(ntb)) - 1;
> > +}
> > +
> > +static u64 vntb_epf_db_vector_mask(struct ntb_dev *ntb, int db_vector)
> > +{
> > + int nr_vec;
> > +
> > + /*
> > + * Doorbell vectors are numbered [0 .. nr_vec - 1], where nr_vec
> > + * excludes the two reserved slots described above.
> > + */
> > + nr_vec = vntb_epf_db_vector_count(ntb);
> > + if (db_vector < 0 || db_vector >= nr_vec)
> > return 0;
> >
> > - return BIT_ULL(ntb_ndev(ntb)->db_count - 2) - 1;
> > + return BIT_ULL(db_vector);
> > }
> >
> > static int vntb_epf_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
> > @@ -1512,6 +1542,8 @@ static const struct ntb_dev_ops vntb_epf_ops = {
> > .spad_count = vntb_epf_spad_count,
> > .peer_mw_count = vntb_epf_peer_mw_count,
> > .db_valid_mask = vntb_epf_db_valid_mask,
> > + .db_vector_count = vntb_epf_db_vector_count,
> > + .db_vector_mask = vntb_epf_db_vector_mask,
> > .db_set_mask = vntb_epf_db_set_mask,
> > .mw_set_trans = vntb_epf_mw_set_trans,
> > .mw_clear_trans = vntb_epf_mw_clear_trans,
> > --
> > 2.51.0
> >
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 06/10] NTB: epf: Document legacy doorbell slot offset in ntb_epf_peer_db_set()
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
` (4 preceding siblings ...)
2026-02-24 13:34 ` [PATCH 05/10] PCI: endpoint: pci-epf-vntb: Implement db_vector_count/mask for doorbells Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 16:46 ` Dave Jiang
2026-02-25 21:03 ` Frank Li
2026-02-24 13:34 ` [PATCH 07/10] NTB: epf: Make db_valid_mask cover only real doorbell bits Koichiro Den
` (3 subsequent siblings)
9 siblings, 2 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
ntb_epf_peer_db_set() uses ffs(db_bits) to select a doorbell to ring.
ffs() returns a 1-based bit index (bit 0 -> 1).
Entry 0 is reserved for link events, so doorbell bit 0 must map to entry
1. However, since the initial commit 812ce2f8d14e ("NTB: Add support for
EPF PCI Non-Transparent Bridge"), the implementation has been adding an
extra +1, ending up using entry 2 for bit 0. Fixing the extra increment
would break interoperability with peers running older kernels.
Keep the legacy behavior and document the offset and the resulting slot
layout to avoid confusion when enabling per-db-vector handling.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/ntb/hw/epf/ntb_hw_epf.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
index d3ecf25a5162..bce7130fec39 100644
--- a/drivers/ntb/hw/epf/ntb_hw_epf.c
+++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
@@ -43,6 +43,18 @@
#define NTB_EPF_DB_DATA(n) (0x34 + (n) * 4)
#define NTB_EPF_DB_OFFSET(n) (0xB4 + (n) * 4)
+/*
+ * Legacy doorbell slot layout when paired with pci-epf-*ntb:
+ *
+ * slot 0 : reserved for link events
+ * slot 1 : unused (historical extra offset)
+ * slot 2 : DB#0
+ * slot 3 : DB#1
+ * ...
+ *
+ * Thus, NTB_EPF_MIN_DB_COUNT=3 means that we at least create vectors for
+ * doorbells DB#0 and DB#1.
+ */
#define NTB_EPF_MIN_DB_COUNT 3
#define NTB_EPF_MAX_DB_COUNT 31
@@ -473,6 +485,14 @@ static int ntb_epf_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
static int ntb_epf_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
{
struct ntb_epf_dev *ndev = ntb_ndev(ntb);
+ /*
+ * ffs() returns a 1-based bit index (bit 0 -> 1).
+ *
+ * With slot 0 reserved for link events, DB#0 would naturally map to
+ * slot 1. Historically an extra +1 offset was added, so DB#0 maps to
+ * slot 2 and slot 1 remains unused. Keep this mapping for
+ * backward-compatibility.
+ */
u32 interrupt_num = ffs(db_bits) + 1;
struct device *dev = ndev->dev;
u32 db_entry_size;
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 06/10] NTB: epf: Document legacy doorbell slot offset in ntb_epf_peer_db_set()
2026-02-24 13:34 ` [PATCH 06/10] NTB: epf: Document legacy doorbell slot offset in ntb_epf_peer_db_set() Koichiro Den
@ 2026-02-25 16:46 ` Dave Jiang
2026-02-25 21:03 ` Frank Li
1 sibling, 0 replies; 32+ messages in thread
From: Dave Jiang @ 2026-02-25 16:46 UTC (permalink / raw)
To: Koichiro Den, Frank.Li, kishon, jdmason, mani, allenbh,
kwilczynski, bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
On 2/24/26 6:34 AM, Koichiro Den wrote:
> ntb_epf_peer_db_set() uses ffs(db_bits) to select a doorbell to ring.
> ffs() returns a 1-based bit index (bit 0 -> 1).
>
> Entry 0 is reserved for link events, so doorbell bit 0 must map to entry
> 1. However, since the initial commit 812ce2f8d14e ("NTB: Add support for
> EPF PCI Non-Transparent Bridge"), the implementation has been adding an
> extra +1, ending up using entry 2 for bit 0. Fixing the extra increment
> would break interoperability with peers running older kernels.
>
> Keep the legacy behavior and document the offset and the resulting slot
> layout to avoid confusion when enabling per-db-vector handling.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/ntb/hw/epf/ntb_hw_epf.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index d3ecf25a5162..bce7130fec39 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -43,6 +43,18 @@
> #define NTB_EPF_DB_DATA(n) (0x34 + (n) * 4)
> #define NTB_EPF_DB_OFFSET(n) (0xB4 + (n) * 4)
>
> +/*
> + * Legacy doorbell slot layout when paired with pci-epf-*ntb:
> + *
> + * slot 0 : reserved for link events
> + * slot 1 : unused (historical extra offset)
> + * slot 2 : DB#0
> + * slot 3 : DB#1
> + * ...
> + *
> + * Thus, NTB_EPF_MIN_DB_COUNT=3 means that we at least create vectors for
> + * doorbells DB#0 and DB#1.
> + */
> #define NTB_EPF_MIN_DB_COUNT 3
> #define NTB_EPF_MAX_DB_COUNT 31
>
> @@ -473,6 +485,14 @@ static int ntb_epf_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
> static int ntb_epf_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
> {
> struct ntb_epf_dev *ndev = ntb_ndev(ntb);
> + /*
> + * ffs() returns a 1-based bit index (bit 0 -> 1).
> + *
> + * With slot 0 reserved for link events, DB#0 would naturally map to
> + * slot 1. Historically an extra +1 offset was added, so DB#0 maps to
> + * slot 2 and slot 1 remains unused. Keep this mapping for
> + * backward-compatibility.
> + */
> u32 interrupt_num = ffs(db_bits) + 1;
> struct device *dev = ndev->dev;
> u32 db_entry_size;
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH 06/10] NTB: epf: Document legacy doorbell slot offset in ntb_epf_peer_db_set()
2026-02-24 13:34 ` [PATCH 06/10] NTB: epf: Document legacy doorbell slot offset in ntb_epf_peer_db_set() Koichiro Den
2026-02-25 16:46 ` Dave Jiang
@ 2026-02-25 21:03 ` Frank Li
1 sibling, 0 replies; 32+ messages in thread
From: Frank Li @ 2026-02-25 21:03 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:55PM +0900, Koichiro Den wrote:
> ntb_epf_peer_db_set() uses ffs(db_bits) to select a doorbell to ring.
> ffs() returns a 1-based bit index (bit 0 -> 1).
>
> Entry 0 is reserved for link events, so doorbell bit 0 must map to entry
> 1. However, since the initial commit 812ce2f8d14e ("NTB: Add support for
> EPF PCI Non-Transparent Bridge"), the implementation has been adding an
> extra +1, ending up using entry 2 for bit 0. Fixing the extra increment
> would break interoperability with peers running older kernels.
>
> Keep the legacy behavior and document the offset and the resulting slot
> layout to avoid confusion when enabling per-db-vector handling.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/ntb/hw/epf/ntb_hw_epf.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index d3ecf25a5162..bce7130fec39 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -43,6 +43,18 @@
> #define NTB_EPF_DB_DATA(n) (0x34 + (n) * 4)
> #define NTB_EPF_DB_OFFSET(n) (0xB4 + (n) * 4)
>
> +/*
> + * Legacy doorbell slot layout when paired with pci-epf-*ntb:
> + *
> + * slot 0 : reserved for link events
> + * slot 1 : unused (historical extra offset)
> + * slot 2 : DB#0
> + * slot 3 : DB#1
> + * ...
> + *
> + * Thus, NTB_EPF_MIN_DB_COUNT=3 means that we at least create vectors for
> + * doorbells DB#0 and DB#1.
> + */
> #define NTB_EPF_MIN_DB_COUNT 3
> #define NTB_EPF_MAX_DB_COUNT 31
>
> @@ -473,6 +485,14 @@ static int ntb_epf_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
> static int ntb_epf_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
> {
> struct ntb_epf_dev *ndev = ntb_ndev(ntb);
> + /*
> + * ffs() returns a 1-based bit index (bit 0 -> 1).
> + *
> + * With slot 0 reserved for link events, DB#0 would naturally map to
> + * slot 1. Historically an extra +1 offset was added, so DB#0 maps to
> + * slot 2 and slot 1 remains unused. Keep this mapping for
> + * backward-compatibility.
> + */
> u32 interrupt_num = ffs(db_bits) + 1;
> struct device *dev = ndev->dev;
> u32 db_entry_size;
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 07/10] NTB: epf: Make db_valid_mask cover only real doorbell bits
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
` (5 preceding siblings ...)
2026-02-24 13:34 ` [PATCH 06/10] NTB: epf: Document legacy doorbell slot offset in ntb_epf_peer_db_set() Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 16:47 ` Dave Jiang
2026-02-25 21:07 ` Frank Li
2026-02-24 13:34 ` [PATCH 08/10] NTB: epf: Report 0-based doorbell vector via ntb_db_event() Koichiro Den
` (2 subsequent siblings)
9 siblings, 2 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
ndev->db_count includes an unused doorbell slot due to the legacy extra
offset in the peer doorbell path. db_valid_mask must cover only the real
doorbell bits and exclude the unused slot.
Set db_valid_mask to BIT_ULL(db_count - 1) - 1.
Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/ntb/hw/epf/ntb_hw_epf.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
index bce7130fec39..ee499eaed4f3 100644
--- a/drivers/ntb/hw/epf/ntb_hw_epf.c
+++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
@@ -580,7 +580,13 @@ static int ntb_epf_init_dev(struct ntb_epf_dev *ndev)
return ret;
}
- ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
+ if (ndev->db_count < NTB_EPF_MIN_DB_COUNT) {
+ dev_err(dev, "db_count %u is less than %u\n", ndev->db_count,
+ NTB_EPF_MIN_DB_COUNT);
+ return -EINVAL;
+ }
+
+ ndev->db_valid_mask = BIT_ULL(ndev->db_count - 1) - 1;
ndev->mw_count = readl(ndev->ctrl_reg + NTB_EPF_MW_COUNT);
ndev->spad_count = readl(ndev->ctrl_reg + NTB_EPF_SPAD_COUNT);
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 07/10] NTB: epf: Make db_valid_mask cover only real doorbell bits
2026-02-24 13:34 ` [PATCH 07/10] NTB: epf: Make db_valid_mask cover only real doorbell bits Koichiro Den
@ 2026-02-25 16:47 ` Dave Jiang
2026-02-26 3:24 ` Koichiro Den
2026-02-25 21:07 ` Frank Li
1 sibling, 1 reply; 32+ messages in thread
From: Dave Jiang @ 2026-02-25 16:47 UTC (permalink / raw)
To: Koichiro Den, Frank.Li, kishon, jdmason, mani, allenbh,
kwilczynski, bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
On 2/24/26 6:34 AM, Koichiro Den wrote:
> ndev->db_count includes an unused doorbell slot due to the legacy extra
> offset in the peer doorbell path. db_valid_mask must cover only the real
> doorbell bits and exclude the unused slot.
>
> Set db_valid_mask to BIT_ULL(db_count - 1) - 1.
>
> Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/ntb/hw/epf/ntb_hw_epf.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index bce7130fec39..ee499eaed4f3 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -580,7 +580,13 @@ static int ntb_epf_init_dev(struct ntb_epf_dev *ndev)
> return ret;
> }
>
> - ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
> + if (ndev->db_count < NTB_EPF_MIN_DB_COUNT) {
> + dev_err(dev, "db_count %u is less than %u\n", ndev->db_count,
> + NTB_EPF_MIN_DB_COUNT);
> + return -EINVAL;
> + }
> +
> + ndev->db_valid_mask = BIT_ULL(ndev->db_count - 1) - 1;
I would suggest adding a comment in the code for why this is for future readers.
DJ
> ndev->mw_count = readl(ndev->ctrl_reg + NTB_EPF_MW_COUNT);
> ndev->spad_count = readl(ndev->ctrl_reg + NTB_EPF_SPAD_COUNT);
>
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH 07/10] NTB: epf: Make db_valid_mask cover only real doorbell bits
2026-02-25 16:47 ` Dave Jiang
@ 2026-02-26 3:24 ` Koichiro Den
0 siblings, 0 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-26 3:24 UTC (permalink / raw)
To: Dave Jiang
Cc: Frank.Li, kishon, jdmason, mani, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Wed, Feb 25, 2026 at 09:47:43AM -0700, Dave Jiang wrote:
>
>
> On 2/24/26 6:34 AM, Koichiro Den wrote:
> > ndev->db_count includes an unused doorbell slot due to the legacy extra
> > offset in the peer doorbell path. db_valid_mask must cover only the real
> > doorbell bits and exclude the unused slot.
> >
> > Set db_valid_mask to BIT_ULL(db_count - 1) - 1.
> >
> > Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> > drivers/ntb/hw/epf/ntb_hw_epf.c | 8 +++++++-
> > 1 file changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> > index bce7130fec39..ee499eaed4f3 100644
> > --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> > +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> > @@ -580,7 +580,13 @@ static int ntb_epf_init_dev(struct ntb_epf_dev *ndev)
> > return ret;
> > }
> >
> > - ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
> > + if (ndev->db_count < NTB_EPF_MIN_DB_COUNT) {
> > + dev_err(dev, "db_count %u is less than %u\n", ndev->db_count,
> > + NTB_EPF_MIN_DB_COUNT);
> > + return -EINVAL;
> > + }
> > +
> > + ndev->db_valid_mask = BIT_ULL(ndev->db_count - 1) - 1;
>
> I would suggest adding a comment in the code for why this is for future readers.
Will do in v2. Thanks for the suggestion.
Koichiro
>
> DJ
>
> > ndev->mw_count = readl(ndev->ctrl_reg + NTB_EPF_MW_COUNT);
> > ndev->spad_count = readl(ndev->ctrl_reg + NTB_EPF_SPAD_COUNT);
> >
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 07/10] NTB: epf: Make db_valid_mask cover only real doorbell bits
2026-02-24 13:34 ` [PATCH 07/10] NTB: epf: Make db_valid_mask cover only real doorbell bits Koichiro Den
2026-02-25 16:47 ` Dave Jiang
@ 2026-02-25 21:07 ` Frank Li
2026-02-26 1:25 ` Koichiro Den
1 sibling, 1 reply; 32+ messages in thread
From: Frank Li @ 2026-02-25 21:07 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:56PM +0900, Koichiro Den wrote:
> ndev->db_count includes an unused doorbell slot due to the legacy extra
> offset in the peer doorbell path. db_valid_mask must cover only the real
> doorbell bits and exclude the unused slot.
>
> Set db_valid_mask to BIT_ULL(db_count - 1) - 1.
db_count -1 or db_count-2, previous patch use db_count-2
Frank
>
> Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/ntb/hw/epf/ntb_hw_epf.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index bce7130fec39..ee499eaed4f3 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -580,7 +580,13 @@ static int ntb_epf_init_dev(struct ntb_epf_dev *ndev)
> return ret;
> }
>
> - ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
> + if (ndev->db_count < NTB_EPF_MIN_DB_COUNT) {
> + dev_err(dev, "db_count %u is less than %u\n", ndev->db_count,
> + NTB_EPF_MIN_DB_COUNT);
> + return -EINVAL;
> + }
> +
> + ndev->db_valid_mask = BIT_ULL(ndev->db_count - 1) - 1;
> ndev->mw_count = readl(ndev->ctrl_reg + NTB_EPF_MW_COUNT);
> ndev->spad_count = readl(ndev->ctrl_reg + NTB_EPF_SPAD_COUNT);
>
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH 07/10] NTB: epf: Make db_valid_mask cover only real doorbell bits
2026-02-25 21:07 ` Frank Li
@ 2026-02-26 1:25 ` Koichiro Den
0 siblings, 0 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-26 1:25 UTC (permalink / raw)
To: Frank Li
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Wed, Feb 25, 2026 at 04:07:14PM -0500, Frank Li wrote:
> On Tue, Feb 24, 2026 at 10:34:56PM +0900, Koichiro Den wrote:
> > ndev->db_count includes an unused doorbell slot due to the legacy extra
> > offset in the peer doorbell path. db_valid_mask must cover only the real
> > doorbell bits and exclude the unused slot.
> >
> > Set db_valid_mask to BIT_ULL(db_count - 1) - 1.
>
> db_count -1 or db_count-2, previous patch use db_count-2
pci-epf-vntb.c (struct epf_ntb) and ntb_hw_epf.c (struct ntb_epf_dev) define
"db_count" slightly differently, historically.
In pci-epf-vntb, db_count is configured via configfs and covers the entire
doorbell register range. The capacity is hard-wired into the shared register
space (e.g. db_data[MAX_DB_COUNT], db_offset[MAX_DB_COUNT]). The peer ringer
applies a +2 offset for DB, and that cannot be changed for interoperability
reasons.
In ntb_hw_epf, db_count subtracts one slot from the full range to exclude the
link event slot (#0). However, it still does not account for the legacy unused
slot (#1).
So effectively we have:
.---- pci-epf-vntb "db_count"
: .-- ntb_hw_epf "db_count"
: :
x #0 link event
x x #1 unused
x x #2 doorbell #0
x x #3 doorbell #1
x x ...
x x #N doorbell #(N-2)
This is why we see the apparent difference between "db_count - 1" and "db_count
- 2" in different places.
Koichiro
>
> Frank
> >
> > Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> > drivers/ntb/hw/epf/ntb_hw_epf.c | 8 +++++++-
> > 1 file changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> > index bce7130fec39..ee499eaed4f3 100644
> > --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> > +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> > @@ -580,7 +580,13 @@ static int ntb_epf_init_dev(struct ntb_epf_dev *ndev)
> > return ret;
> > }
> >
> > - ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
> > + if (ndev->db_count < NTB_EPF_MIN_DB_COUNT) {
> > + dev_err(dev, "db_count %u is less than %u\n", ndev->db_count,
> > + NTB_EPF_MIN_DB_COUNT);
> > + return -EINVAL;
> > + }
> > +
> > + ndev->db_valid_mask = BIT_ULL(ndev->db_count - 1) - 1;
> > ndev->mw_count = readl(ndev->ctrl_reg + NTB_EPF_MW_COUNT);
> > ndev->spad_count = readl(ndev->ctrl_reg + NTB_EPF_SPAD_COUNT);
> >
> > --
> > 2.51.0
> >
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 08/10] NTB: epf: Report 0-based doorbell vector via ntb_db_event()
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
` (6 preceding siblings ...)
2026-02-24 13:34 ` [PATCH 07/10] NTB: epf: Make db_valid_mask cover only real doorbell bits Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 16:59 ` Dave Jiang
2026-02-25 21:09 ` Frank Li
2026-02-24 13:34 ` [PATCH 09/10] NTB: epf: Fix doorbell bitmask handling in db_read/db_clear Koichiro Den
2026-02-24 13:34 ` [PATCH 10/10] NTB: epf: Implement db_vector_count/mask for doorbells Koichiro Den
9 siblings, 2 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
ntb_db_event() expects the vector number to be relative to the first
doorbell vector starting at 0.
Vector 0 is reserved for link events in the EPF driver, so doorbells
start at vector 1. However, both supported peers (ntb_hw_epf with
pci-epf-ntb, and pci-epf-vntb) have historically skipped vector 1 and
started doorbells at vector 2.
Pass (irq_no - 2) to ntb_db_event() so doorbells are reported as 0..N-1.
If irq_no == 1 is ever observed, treat it as DB#0 and emit a warning, as
this would indicate an unexpected change in the slot layout.
Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/ntb/hw/epf/ntb_hw_epf.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
index ee499eaed4f3..00956ab2fbf5 100644
--- a/drivers/ntb/hw/epf/ntb_hw_epf.c
+++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
@@ -333,10 +333,15 @@ static irqreturn_t ntb_epf_vec_isr(int irq, void *dev)
irq_no = irq - pci_irq_vector(ndev->ntb.pdev, 0);
ndev->db_val = irq_no + 1;
- if (irq_no == 0)
+ if (irq_no == 0) {
ntb_link_event(&ndev->ntb);
- else
- ntb_db_event(&ndev->ntb, irq_no);
+ } else if (irq_no == 1) {
+ dev_warn_ratelimited(ndev->dev,
+ "Unexpected irq_no 1 received. Treat it as DB#0.\n");
+ ntb_db_event(&ndev->ntb, 0);
+ } else {
+ ntb_db_event(&ndev->ntb, irq_no - 2);
+ }
return IRQ_HANDLED;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 08/10] NTB: epf: Report 0-based doorbell vector via ntb_db_event()
2026-02-24 13:34 ` [PATCH 08/10] NTB: epf: Report 0-based doorbell vector via ntb_db_event() Koichiro Den
@ 2026-02-25 16:59 ` Dave Jiang
2026-02-26 3:17 ` Koichiro Den
2026-02-25 21:09 ` Frank Li
1 sibling, 1 reply; 32+ messages in thread
From: Dave Jiang @ 2026-02-25 16:59 UTC (permalink / raw)
To: Koichiro Den, Frank.Li, kishon, jdmason, mani, allenbh,
kwilczynski, bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
On 2/24/26 6:34 AM, Koichiro Den wrote:
> ntb_db_event() expects the vector number to be relative to the first
> doorbell vector starting at 0.
>
> Vector 0 is reserved for link events in the EPF driver, so doorbells
> start at vector 1. However, both supported peers (ntb_hw_epf with
> pci-epf-ntb, and pci-epf-vntb) have historically skipped vector 1 and
> started doorbells at vector 2.
>
> Pass (irq_no - 2) to ntb_db_event() so doorbells are reported as 0..N-1.
> If irq_no == 1 is ever observed, treat it as DB#0 and emit a warning, as
> this would indicate an unexpected change in the slot layout.
>
> Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/ntb/hw/epf/ntb_hw_epf.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index ee499eaed4f3..00956ab2fbf5 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -333,10 +333,15 @@ static irqreturn_t ntb_epf_vec_isr(int irq, void *dev)
> irq_no = irq - pci_irq_vector(ndev->ntb.pdev, 0);
> ndev->db_val = irq_no + 1;
>
> - if (irq_no == 0)
> + if (irq_no == 0) {
> ntb_link_event(&ndev->ntb);
> - else
> - ntb_db_event(&ndev->ntb, irq_no);
> + } else if (irq_no == 1) {
Given that 0 and 1 have specific meanings, maybe create a enum with appropriate naming to make it more clear. Maybe something like this or however you want to name them:
enum EPF_IRQ_SLOT {
EPF_IRQ_LINK = 0,
EPF_IRQ_RESERVED_DB,
EPF_IRQ_DB_START,
};
> + dev_warn_ratelimited(ndev->dev,
> + "Unexpected irq_no 1 received. Treat it as DB#0.\n");
> + ntb_db_event(&ndev->ntb, 0);
> + } else {
> + ntb_db_event(&ndev->ntb, irq_no - 2);
And then here you can do
ntb_db_event(&ndev->ntb, irq_no - EPF_IRQ_DB_START);
> + }
>
> return IRQ_HANDLED;
> }
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH 08/10] NTB: epf: Report 0-based doorbell vector via ntb_db_event()
2026-02-25 16:59 ` Dave Jiang
@ 2026-02-26 3:17 ` Koichiro Den
0 siblings, 0 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-26 3:17 UTC (permalink / raw)
To: Dave Jiang, Frank.Li
Cc: kishon, jdmason, mani, allenbh, kwilczynski, bhelgaas, jbrunet,
lpieralisi, linux-pci, ntb, linux-kernel
On Wed, Feb 25, 2026 at 09:59:46AM -0700, Dave Jiang wrote:
>
>
> On 2/24/26 6:34 AM, Koichiro Den wrote:
> > ntb_db_event() expects the vector number to be relative to the first
> > doorbell vector starting at 0.
> >
> > Vector 0 is reserved for link events in the EPF driver, so doorbells
> > start at vector 1. However, both supported peers (ntb_hw_epf with
> > pci-epf-ntb, and pci-epf-vntb) have historically skipped vector 1 and
> > started doorbells at vector 2.
> >
> > Pass (irq_no - 2) to ntb_db_event() so doorbells are reported as 0..N-1.
> > If irq_no == 1 is ever observed, treat it as DB#0 and emit a warning, as
> > this would indicate an unexpected change in the slot layout.
> >
> > Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> > drivers/ntb/hw/epf/ntb_hw_epf.c | 11 ++++++++---
> > 1 file changed, 8 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> > index ee499eaed4f3..00956ab2fbf5 100644
> > --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> > +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> > @@ -333,10 +333,15 @@ static irqreturn_t ntb_epf_vec_isr(int irq, void *dev)
> > irq_no = irq - pci_irq_vector(ndev->ntb.pdev, 0);
> > ndev->db_val = irq_no + 1;
> >
> > - if (irq_no == 0)
> > + if (irq_no == 0) {
> > ntb_link_event(&ndev->ntb);
> > - else
> > - ntb_db_event(&ndev->ntb, irq_no);
> > + } else if (irq_no == 1) {
>
> Given that 0 and 1 have specific meanings, maybe create a enum with appropriate naming to make it more clear. Maybe something like this or however you want to name them:
>
> enum EPF_IRQ_SLOT {
> EPF_IRQ_LINK = 0,
> EPF_IRQ_RESERVED_DB,
> EPF_IRQ_DB_START,
> };
Thanks for the suggestion, that sounds reasonable. I'd be happy to use the enum
names as proposed.
Frank, I'd like to introduce the same kind of enum in Patch 3 to eliminate
0/1/2 magic numbers for clarity and consistency. Please let me know if you have
a different view.
If you agree, I'll adjust vNTB part accordingly, and keep your Reviewed-by tags
if you're ok with that.
Thanks,
Koichiro
> > + dev_warn_ratelimited(ndev->dev,
> > + "Unexpected irq_no 1 received. Treat it as DB#0.\n");
> > + ntb_db_event(&ndev->ntb, 0);
> > + } else {
> > + ntb_db_event(&ndev->ntb, irq_no - 2);
>
> And then here you can do
> ntb_db_event(&ndev->ntb, irq_no - EPF_IRQ_DB_START);
>
> > + }
> >
> > return IRQ_HANDLED;
> > }
>
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 08/10] NTB: epf: Report 0-based doorbell vector via ntb_db_event()
2026-02-24 13:34 ` [PATCH 08/10] NTB: epf: Report 0-based doorbell vector via ntb_db_event() Koichiro Den
2026-02-25 16:59 ` Dave Jiang
@ 2026-02-25 21:09 ` Frank Li
1 sibling, 0 replies; 32+ messages in thread
From: Frank Li @ 2026-02-25 21:09 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:57PM +0900, Koichiro Den wrote:
> ntb_db_event() expects the vector number to be relative to the first
> doorbell vector starting at 0.
>
> Vector 0 is reserved for link events in the EPF driver, so doorbells
> start at vector 1. However, both supported peers (ntb_hw_epf with
> pci-epf-ntb, and pci-epf-vntb) have historically skipped vector 1 and
> started doorbells at vector 2.
>
> Pass (irq_no - 2) to ntb_db_event() so doorbells are reported as 0..N-1.
> If irq_no == 1 is ever observed, treat it as DB#0 and emit a warning, as
> this would indicate an unexpected change in the slot layout.
>
> Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/ntb/hw/epf/ntb_hw_epf.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index ee499eaed4f3..00956ab2fbf5 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -333,10 +333,15 @@ static irqreturn_t ntb_epf_vec_isr(int irq, void *dev)
> irq_no = irq - pci_irq_vector(ndev->ntb.pdev, 0);
> ndev->db_val = irq_no + 1;
>
> - if (irq_no == 0)
> + if (irq_no == 0) {
> ntb_link_event(&ndev->ntb);
> - else
> - ntb_db_event(&ndev->ntb, irq_no);
> + } else if (irq_no == 1) {
> + dev_warn_ratelimited(ndev->dev,
> + "Unexpected irq_no 1 received. Treat it as DB#0.\n");
> + ntb_db_event(&ndev->ntb, 0);
> + } else {
> + ntb_db_event(&ndev->ntb, irq_no - 2);
> + }
>
> return IRQ_HANDLED;
> }
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 09/10] NTB: epf: Fix doorbell bitmask handling in db_read/db_clear
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
` (7 preceding siblings ...)
2026-02-24 13:34 ` [PATCH 08/10] NTB: epf: Report 0-based doorbell vector via ntb_db_event() Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 17:04 ` Dave Jiang
2026-02-25 21:11 ` Frank Li
2026-02-24 13:34 ` [PATCH 10/10] NTB: epf: Implement db_vector_count/mask for doorbells Koichiro Den
9 siblings, 2 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
The EPF driver currently stores the incoming doorbell as a vector number
(irq_no + 1) in db_val and db_clear() clears all bits unconditionally.
This breaks db_read()/db_clear() semantics when multiple doorbells are
used.
Store doorbells as a bitmask (BIT_ULL(vector)) and make
db_clear(db_bits) clear only the specified bits. Use atomic64 operations
as db_val is updated from interrupt context.
Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/ntb/hw/epf/ntb_hw_epf.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
index 00956ab2fbf5..0018adc35f16 100644
--- a/drivers/ntb/hw/epf/ntb_hw_epf.c
+++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
@@ -6,6 +6,7 @@
* Author: Kishon Vijay Abraham I <kishon@ti.com>
*/
+#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -102,7 +103,7 @@ struct ntb_epf_dev {
unsigned int self_spad;
unsigned int peer_spad;
- int db_val;
+ atomic64_t db_val;
u64 db_valid_mask;
};
@@ -331,15 +332,16 @@ static irqreturn_t ntb_epf_vec_isr(int irq, void *dev)
int irq_no;
irq_no = irq - pci_irq_vector(ndev->ntb.pdev, 0);
- ndev->db_val = irq_no + 1;
if (irq_no == 0) {
ntb_link_event(&ndev->ntb);
} else if (irq_no == 1) {
dev_warn_ratelimited(ndev->dev,
"Unexpected irq_no 1 received. Treat it as DB#0.\n");
+ atomic64_or(BIT_ULL(0), &ndev->db_val);
ntb_db_event(&ndev->ntb, 0);
} else {
+ atomic64_or(BIT_ULL(irq_no - 2), &ndev->db_val);
ntb_db_event(&ndev->ntb, irq_no - 2);
}
@@ -524,7 +526,7 @@ static u64 ntb_epf_db_read(struct ntb_dev *ntb)
{
struct ntb_epf_dev *ndev = ntb_ndev(ntb);
- return ndev->db_val;
+ return atomic64_read(&ndev->db_val);
}
static int ntb_epf_db_clear_mask(struct ntb_dev *ntb, u64 db_bits)
@@ -536,7 +538,7 @@ static int ntb_epf_db_clear(struct ntb_dev *ntb, u64 db_bits)
{
struct ntb_epf_dev *ndev = ntb_ndev(ntb);
- ndev->db_val = 0;
+ atomic64_and(~db_bits, &ndev->db_val);
return 0;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 09/10] NTB: epf: Fix doorbell bitmask handling in db_read/db_clear
2026-02-24 13:34 ` [PATCH 09/10] NTB: epf: Fix doorbell bitmask handling in db_read/db_clear Koichiro Den
@ 2026-02-25 17:04 ` Dave Jiang
2026-02-25 21:11 ` Frank Li
1 sibling, 0 replies; 32+ messages in thread
From: Dave Jiang @ 2026-02-25 17:04 UTC (permalink / raw)
To: Koichiro Den, Frank.Li, kishon, jdmason, mani, allenbh,
kwilczynski, bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
On 2/24/26 6:34 AM, Koichiro Den wrote:
> The EPF driver currently stores the incoming doorbell as a vector number
> (irq_no + 1) in db_val and db_clear() clears all bits unconditionally.
> This breaks db_read()/db_clear() semantics when multiple doorbells are
> used.
>
> Store doorbells as a bitmask (BIT_ULL(vector)) and make
> db_clear(db_bits) clear only the specified bits. Use atomic64 operations
> as db_val is updated from interrupt context.
>
> Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/ntb/hw/epf/ntb_hw_epf.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index 00956ab2fbf5..0018adc35f16 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -6,6 +6,7 @@
> * Author: Kishon Vijay Abraham I <kishon@ti.com>
> */
>
> +#include <linux/atomic.h>
> #include <linux/delay.h>
> #include <linux/module.h>
> #include <linux/pci.h>
> @@ -102,7 +103,7 @@ struct ntb_epf_dev {
> unsigned int self_spad;
> unsigned int peer_spad;
>
> - int db_val;
> + atomic64_t db_val;
> u64 db_valid_mask;
> };
>
> @@ -331,15 +332,16 @@ static irqreturn_t ntb_epf_vec_isr(int irq, void *dev)
> int irq_no;
>
> irq_no = irq - pci_irq_vector(ndev->ntb.pdev, 0);
> - ndev->db_val = irq_no + 1;
>
> if (irq_no == 0) {
> ntb_link_event(&ndev->ntb);
> } else if (irq_no == 1) {
> dev_warn_ratelimited(ndev->dev,
> "Unexpected irq_no 1 received. Treat it as DB#0.\n");
> + atomic64_or(BIT_ULL(0), &ndev->db_val);
> ntb_db_event(&ndev->ntb, 0);
> } else {
> + atomic64_or(BIT_ULL(irq_no - 2), &ndev->db_val);
Again here the bits probably can use a define or enum instead of magic numbers.
DJ
> ntb_db_event(&ndev->ntb, irq_no - 2);
> }
>
> @@ -524,7 +526,7 @@ static u64 ntb_epf_db_read(struct ntb_dev *ntb)
> {
> struct ntb_epf_dev *ndev = ntb_ndev(ntb);
>
> - return ndev->db_val;
> + return atomic64_read(&ndev->db_val);
> }
>
> static int ntb_epf_db_clear_mask(struct ntb_dev *ntb, u64 db_bits)
> @@ -536,7 +538,7 @@ static int ntb_epf_db_clear(struct ntb_dev *ntb, u64 db_bits)
> {
> struct ntb_epf_dev *ndev = ntb_ndev(ntb);
>
> - ndev->db_val = 0;
> + atomic64_and(~db_bits, &ndev->db_val);
>
> return 0;
> }
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH 09/10] NTB: epf: Fix doorbell bitmask handling in db_read/db_clear
2026-02-24 13:34 ` [PATCH 09/10] NTB: epf: Fix doorbell bitmask handling in db_read/db_clear Koichiro Den
2026-02-25 17:04 ` Dave Jiang
@ 2026-02-25 21:11 ` Frank Li
1 sibling, 0 replies; 32+ messages in thread
From: Frank Li @ 2026-02-25 21:11 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:58PM +0900, Koichiro Den wrote:
> The EPF driver currently stores the incoming doorbell as a vector number
> (irq_no + 1) in db_val and db_clear() clears all bits unconditionally.
> This breaks db_read()/db_clear() semantics when multiple doorbells are
> used.
>
> Store doorbells as a bitmask (BIT_ULL(vector)) and make
> db_clear(db_bits) clear only the specified bits. Use atomic64 operations
> as db_val is updated from interrupt context.
>
> Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/ntb/hw/epf/ntb_hw_epf.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index 00956ab2fbf5..0018adc35f16 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -6,6 +6,7 @@
> * Author: Kishon Vijay Abraham I <kishon@ti.com>
> */
>
> +#include <linux/atomic.h>
> #include <linux/delay.h>
> #include <linux/module.h>
> #include <linux/pci.h>
> @@ -102,7 +103,7 @@ struct ntb_epf_dev {
> unsigned int self_spad;
> unsigned int peer_spad;
>
> - int db_val;
> + atomic64_t db_val;
> u64 db_valid_mask;
> };
>
> @@ -331,15 +332,16 @@ static irqreturn_t ntb_epf_vec_isr(int irq, void *dev)
> int irq_no;
>
> irq_no = irq - pci_irq_vector(ndev->ntb.pdev, 0);
> - ndev->db_val = irq_no + 1;
>
> if (irq_no == 0) {
> ntb_link_event(&ndev->ntb);
> } else if (irq_no == 1) {
> dev_warn_ratelimited(ndev->dev,
> "Unexpected irq_no 1 received. Treat it as DB#0.\n");
> + atomic64_or(BIT_ULL(0), &ndev->db_val);
> ntb_db_event(&ndev->ntb, 0);
> } else {
> + atomic64_or(BIT_ULL(irq_no - 2), &ndev->db_val);
> ntb_db_event(&ndev->ntb, irq_no - 2);
> }
>
> @@ -524,7 +526,7 @@ static u64 ntb_epf_db_read(struct ntb_dev *ntb)
> {
> struct ntb_epf_dev *ndev = ntb_ndev(ntb);
>
> - return ndev->db_val;
> + return atomic64_read(&ndev->db_val);
> }
>
> static int ntb_epf_db_clear_mask(struct ntb_dev *ntb, u64 db_bits)
> @@ -536,7 +538,7 @@ static int ntb_epf_db_clear(struct ntb_dev *ntb, u64 db_bits)
> {
> struct ntb_epf_dev *ndev = ntb_ndev(ntb);
>
> - ndev->db_val = 0;
> + atomic64_and(~db_bits, &ndev->db_val);
>
> return 0;
> }
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 10/10] NTB: epf: Implement db_vector_count/mask for doorbells
2026-02-24 13:34 [PATCH 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset Koichiro Den
` (8 preceding siblings ...)
2026-02-24 13:34 ` [PATCH 09/10] NTB: epf: Fix doorbell bitmask handling in db_read/db_clear Koichiro Den
@ 2026-02-24 13:34 ` Koichiro Den
2026-02-25 17:09 ` Dave Jiang
2026-02-25 21:13 ` Frank Li
9 siblings, 2 replies; 32+ messages in thread
From: Koichiro Den @ 2026-02-24 13:34 UTC (permalink / raw)
To: Frank.Li, kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski,
bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
Implement .db_vector_count and .db_vector_mask so ntb core/clients can
map doorbell events to per-vector work.
Report vectors as 0..(db_count - 2) (skipping the unused slot) and
return BIT_ULL(db_vector) for the corresponding doorbell bit.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/ntb/hw/epf/ntb_hw_epf.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
index 0018adc35f16..7c76039a79d2 100644
--- a/drivers/ntb/hw/epf/ntb_hw_epf.c
+++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
@@ -414,6 +414,34 @@ static u64 ntb_epf_db_valid_mask(struct ntb_dev *ntb)
return ntb_ndev(ntb)->db_valid_mask;
}
+static int ntb_epf_db_vector_count(struct ntb_dev *ntb)
+{
+ struct ntb_epf_dev *ndev = ntb_ndev(ntb);
+
+ /*
+ * ndev->db_count includes an extra skipped slot due to the legacy
+ * doorbell layout. Expose only the real doorbell vectors.
+ */
+ if (ndev->db_count < 1)
+ return 0;
+
+ return ntb_ndev(ntb)->db_count - 1;
+}
+
+static u64 ntb_epf_db_vector_mask(struct ntb_dev *ntb, int db_vector)
+{
+ struct ntb_epf_dev *ndev = ntb_ndev(ntb);
+
+ /*
+ * ndev->db_count includes one skipped slot in the legacy layout. Valid
+ * doorbell vectors are therefore [0 .. (db_count - 2)].
+ */
+ if (db_vector < 0 || db_vector >= ndev->db_count - 1)
+ return 0;
+
+ return BIT_ULL(db_vector);
+}
+
static int ntb_epf_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
{
return 0;
@@ -548,6 +576,8 @@ static const struct ntb_dev_ops ntb_epf_ops = {
.spad_count = ntb_epf_spad_count,
.peer_mw_count = ntb_epf_peer_mw_count,
.db_valid_mask = ntb_epf_db_valid_mask,
+ .db_vector_count = ntb_epf_db_vector_count,
+ .db_vector_mask = ntb_epf_db_vector_mask,
.db_set_mask = ntb_epf_db_set_mask,
.mw_set_trans = ntb_epf_mw_set_trans,
.mw_clear_trans = ntb_epf_mw_clear_trans,
--
2.51.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 10/10] NTB: epf: Implement db_vector_count/mask for doorbells
2026-02-24 13:34 ` [PATCH 10/10] NTB: epf: Implement db_vector_count/mask for doorbells Koichiro Den
@ 2026-02-25 17:09 ` Dave Jiang
2026-02-25 21:13 ` Frank Li
1 sibling, 0 replies; 32+ messages in thread
From: Dave Jiang @ 2026-02-25 17:09 UTC (permalink / raw)
To: Koichiro Den, Frank.Li, kishon, jdmason, mani, allenbh,
kwilczynski, bhelgaas, jbrunet, lpieralisi
Cc: linux-pci, ntb, linux-kernel
On 2/24/26 6:34 AM, Koichiro Den wrote:
> Implement .db_vector_count and .db_vector_mask so ntb core/clients can
> map doorbell events to per-vector work.
>
> Report vectors as 0..(db_count - 2) (skipping the unused slot) and
> return BIT_ULL(db_vector) for the corresponding doorbell bit.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/ntb/hw/epf/ntb_hw_epf.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index 0018adc35f16..7c76039a79d2 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -414,6 +414,34 @@ static u64 ntb_epf_db_valid_mask(struct ntb_dev *ntb)
> return ntb_ndev(ntb)->db_valid_mask;
> }
>
> +static int ntb_epf_db_vector_count(struct ntb_dev *ntb)
> +{
> + struct ntb_epf_dev *ndev = ntb_ndev(ntb);
> +
> + /*
> + * ndev->db_count includes an extra skipped slot due to the legacy
> + * doorbell layout. Expose only the real doorbell vectors.
> + */
> + if (ndev->db_count < 1)
> + return 0;
> +
> + return ntb_ndev(ntb)->db_count - 1;
> +}
> +
> +static u64 ntb_epf_db_vector_mask(struct ntb_dev *ntb, int db_vector)
> +{
> + struct ntb_epf_dev *ndev = ntb_ndev(ntb);
> +
> + /*
> + * ndev->db_count includes one skipped slot in the legacy layout. Valid
> + * doorbell vectors are therefore [0 .. (db_count - 2)].
> + */
> + if (db_vector < 0 || db_vector >= ndev->db_count - 1)
> + return 0;
> +
> + return BIT_ULL(db_vector);
> +}
> +
> static int ntb_epf_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
> {
> return 0;
> @@ -548,6 +576,8 @@ static const struct ntb_dev_ops ntb_epf_ops = {
> .spad_count = ntb_epf_spad_count,
> .peer_mw_count = ntb_epf_peer_mw_count,
> .db_valid_mask = ntb_epf_db_valid_mask,
> + .db_vector_count = ntb_epf_db_vector_count,
> + .db_vector_mask = ntb_epf_db_vector_mask,
> .db_set_mask = ntb_epf_db_set_mask,
> .mw_set_trans = ntb_epf_mw_set_trans,
> .mw_clear_trans = ntb_epf_mw_clear_trans,
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH 10/10] NTB: epf: Implement db_vector_count/mask for doorbells
2026-02-24 13:34 ` [PATCH 10/10] NTB: epf: Implement db_vector_count/mask for doorbells Koichiro Den
2026-02-25 17:09 ` Dave Jiang
@ 2026-02-25 21:13 ` Frank Li
1 sibling, 0 replies; 32+ messages in thread
From: Frank Li @ 2026-02-25 21:13 UTC (permalink / raw)
To: Koichiro Den
Cc: kishon, jdmason, mani, dave.jiang, allenbh, kwilczynski, bhelgaas,
jbrunet, lpieralisi, linux-pci, ntb, linux-kernel
On Tue, Feb 24, 2026 at 10:34:59PM +0900, Koichiro Den wrote:
> Implement .db_vector_count and .db_vector_mask so ntb core/clients can
> map doorbell events to per-vector work.
>
> Report vectors as 0..(db_count - 2) (skipping the unused slot) and
> return BIT_ULL(db_vector) for the corresponding doorbell bit.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/ntb/hw/epf/ntb_hw_epf.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
> index 0018adc35f16..7c76039a79d2 100644
> --- a/drivers/ntb/hw/epf/ntb_hw_epf.c
> +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
> @@ -414,6 +414,34 @@ static u64 ntb_epf_db_valid_mask(struct ntb_dev *ntb)
> return ntb_ndev(ntb)->db_valid_mask;
> }
>
> +static int ntb_epf_db_vector_count(struct ntb_dev *ntb)
> +{
> + struct ntb_epf_dev *ndev = ntb_ndev(ntb);
> +
> + /*
> + * ndev->db_count includes an extra skipped slot due to the legacy
> + * doorbell layout. Expose only the real doorbell vectors.
> + */
> + if (ndev->db_count < 1)
> + return 0;
> +
> + return ntb_ndev(ntb)->db_count - 1;
return max(ntb_ndev(ntb)->db_count - 1, 0);
Anyway: Reviewed-by: Frank Li <Frank.Li@nxp.com>
> +}
> +
> +static u64 ntb_epf_db_vector_mask(struct ntb_dev *ntb, int db_vector)
> +{
> + struct ntb_epf_dev *ndev = ntb_ndev(ntb);
> +
> + /*
> + * ndev->db_count includes one skipped slot in the legacy layout. Valid
> + * doorbell vectors are therefore [0 .. (db_count - 2)].
> + */
> + if (db_vector < 0 || db_vector >= ndev->db_count - 1)
> + return 0;
> +
> + return BIT_ULL(db_vector);
> +}
> +
> static int ntb_epf_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
> {
> return 0;
> @@ -548,6 +576,8 @@ static const struct ntb_dev_ops ntb_epf_ops = {
> .spad_count = ntb_epf_spad_count,
> .peer_mw_count = ntb_epf_peer_mw_count,
> .db_valid_mask = ntb_epf_db_valid_mask,
> + .db_vector_count = ntb_epf_db_vector_count,
> + .db_vector_mask = ntb_epf_db_vector_mask,
> .db_set_mask = ntb_epf_db_set_mask,
> .mw_set_trans = ntb_epf_mw_set_trans,
> .mw_clear_trans = ntb_epf_mw_clear_trans,
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread