[PATCH 09/11] NTB/msi: Require a singleton memory window

Koichiro Den <[email protected]> Tue, 4 Aug 2026 03:04:36 +0900
Newsgroups dev.linux.lists.ntb,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci
Message-ID <[email protected]>
NTB MSI reserves the last MW for each peer and programs it
independently. A member of a larger translation group cannot be reserved
on its own.

Reject such layouts during initialization. This lets ntb_transport keep
the whole group for data and fall back to doorbells.

Signed-off-by: Koichiro Den <[email protected]>
---
 drivers/ntb/msi.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/ntb/msi.c b/drivers/ntb/msi.c
index 6817d504c12a..029edcf40078 100644
--- a/drivers/ntb/msi.c
+++ b/drivers/ntb/msi.c
@@ -24,7 +24,8 @@ struct ntb_msi {
  * the peer memory windows.
  *
  * This function reserves the last N outbound memory windows (where N
- * is the number of peers).
+ * is the number of peers). The corresponding inbound memory windows must
+ * each form a singleton translation group.
  *
  * Return: Zero on success, otherwise a negative error number.
  */
@@ -33,6 +34,7 @@ int ntb_msi_init(struct ntb_dev *ntb,
 {
 	phys_addr_t mw_phys_addr;
 	resource_size_t mw_size;
+	int first, count;
 	int peer_widx;
 	int peers;
 	int ret;
@@ -42,6 +44,21 @@ int ntb_msi_init(struct ntb_dev *ntb,
 	if (peers <= 0)
 		return -EINVAL;
 
+	if (ntb->ops->mw_get_trans_group) {
+		for (i = 0; i < peers; i++) {
+			peer_widx = ntb_peer_highest_mw_idx(ntb, i);
+			if (peer_widx < 0)
+				return peer_widx;
+
+			ret = ntb_mw_get_trans_group(ntb, i, peer_widx, &first,
+						     &count);
+			if (ret)
+				return ret;
+			if (first != peer_widx || count != 1)
+				return -EOPNOTSUPP;
+		}
+	}
+
 	ntb->msi = devm_kzalloc(&ntb->dev, struct_size(ntb->msi, peer_mws, peers),
 				GFP_KERNEL);
 	if (!ntb->msi)
-- 
2.51.0