patches.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Jerome Brunet <jbrunet@baylibre.com>,
	Jon Mason <jdmason@kudzu.us>, Sasha Levin <sashal@kernel.org>,
	alexandre.f.demers@gmail.com, Frank.Li@nxp.com,
	alexander.deucher@amd.com
Subject: [PATCH AUTOSEL 6.17-6.1] NTB: epf: Allow arbitrary BAR mapping
Date: Sun, 26 Oct 2025 10:48:44 -0400	[thread overview]
Message-ID: <20251026144958.26750-6-sashal@kernel.org> (raw)
In-Reply-To: <20251026144958.26750-1-sashal@kernel.org>

From: Jerome Brunet <jbrunet@baylibre.com>

[ Upstream commit 5ad865862a0fd349163243e1834ed98ba9b81905 ]

The NTB epf host driver assumes the BAR number associated with a memory
window is just incremented from the BAR number associated with MW1. This
seems to have been enough so far but this is not really how the endpoint
side work and the two could easily become mis-aligned.

ntb_epf_mw_to_bar() even assumes that the BAR number is the memory window
index + 2, which means the function only returns a proper result if BAR_2
is associated with MW1.

Instead, fully describe and allow arbitrary NTB BAR mapping.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Jon Mason <jdmason@kudzu.us>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

YES
- The patch fixes a real bug: `ntb_epf_mw_to_bar()` no longer hard-codes
  `idx + 2` but queries the per-platform BAR map
  (`drivers/ntb/hw/epf/ntb_hw_epf.c:110`), so code that computes MW
  alignment and size now points at the actual resource instead of the
  doorbell BAR (previously breaking i.MX8, whose MW1 lives at BAR4).
- The BAR map itself is formalized via `barno_map` and explicit arrays
  for each supported platform (`drivers/ntb/hw/epf/ntb_hw_epf.c:52` and
  `drivers/ntb/hw/epf/ntb_hw_epf.c:578`), eliminating the prior “MW1
  must be BAR2 and everything is sequential” assumption that caused
  host/endpoint mismatches in real deployments.
- Memory-window helpers now reuse that mapping and bail out cleanly if
  the endpoint reports a window without a backing BAR
  (`drivers/ntb/hw/epf/ntb_hw_epf.c:141`,
  `drivers/ntb/hw/epf/ntb_hw_epf.c:413`), and the new guard on
  `mw_count` prevents overrunning the table
  (`drivers/ntb/hw/epf/ntb_hw_epf.c:451`). Together these changes let
  the existing NTB EPF hardware actually expose its windows safely.
- Risk is contained: the refactor stays inside the NTB EPF host driver,
  keeps the public NTB API untouched, and the new data is static per-
  device, so stable backport fallout should be low compared to the very
  real malfunction the current code has on non-TI layouts.

Given it repairs functionality that never worked correctly for at least
the NXP i.MX8 configuration, this is a good candidate for stable.

 drivers/ntb/hw/epf/ntb_hw_epf.c | 103 ++++++++++++++++----------------
 1 file changed, 53 insertions(+), 50 deletions(-)

diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
index 00f0e78f685bf..2b51156e01b0f 100644
--- a/drivers/ntb/hw/epf/ntb_hw_epf.c
+++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
@@ -49,6 +49,7 @@
 #define NTB_EPF_COMMAND_TIMEOUT	1000 /* 1 Sec */
 
 enum pci_barno {
+	NO_BAR = -1,
 	BAR_0,
 	BAR_1,
 	BAR_2,
@@ -57,16 +58,26 @@ enum pci_barno {
 	BAR_5,
 };
 
+enum epf_ntb_bar {
+	BAR_CONFIG,
+	BAR_PEER_SPAD,
+	BAR_DB,
+	BAR_MW1,
+	BAR_MW2,
+	BAR_MW3,
+	BAR_MW4,
+	NTB_BAR_NUM,
+};
+
+#define NTB_EPF_MAX_MW_COUNT	(NTB_BAR_NUM - BAR_MW1)
+
 struct ntb_epf_dev {
 	struct ntb_dev ntb;
 	struct device *dev;
 	/* Mutex to protect providing commands to NTB EPF */
 	struct mutex cmd_lock;
 
-	enum pci_barno ctrl_reg_bar;
-	enum pci_barno peer_spad_reg_bar;
-	enum pci_barno db_reg_bar;
-	enum pci_barno mw_bar;
+	const enum pci_barno *barno_map;
 
 	unsigned int mw_count;
 	unsigned int spad_count;
@@ -85,17 +96,6 @@ struct ntb_epf_dev {
 
 #define ntb_ndev(__ntb) container_of(__ntb, struct ntb_epf_dev, ntb)
 
-struct ntb_epf_data {
-	/* BAR that contains both control region and self spad region */
-	enum pci_barno ctrl_reg_bar;
-	/* BAR that contains peer spad region */
-	enum pci_barno peer_spad_reg_bar;
-	/* BAR that contains Doorbell region and Memory window '1' */
-	enum pci_barno db_reg_bar;
-	/* BAR that contains memory windows*/
-	enum pci_barno mw_bar;
-};
-
 static int ntb_epf_send_command(struct ntb_epf_dev *ndev, u32 command,
 				u32 argument)
 {
@@ -144,7 +144,7 @@ static int ntb_epf_mw_to_bar(struct ntb_epf_dev *ndev, int idx)
 		return -EINVAL;
 	}
 
-	return idx + 2;
+	return ndev->barno_map[BAR_MW1 + idx];
 }
 
 static int ntb_epf_mw_count(struct ntb_dev *ntb, int pidx)
@@ -413,7 +413,9 @@ static int ntb_epf_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
 		return -EINVAL;
 	}
 
-	bar = idx + ndev->mw_bar;
+	bar = ntb_epf_mw_to_bar(ndev, idx);
+	if (bar < 0)
+		return bar;
 
 	mw_size = pci_resource_len(ntb->pdev, bar);
 
@@ -455,7 +457,9 @@ static int ntb_epf_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
 	if (idx == 0)
 		offset = readl(ndev->ctrl_reg + NTB_EPF_MW1_OFFSET);
 
-	bar = idx + ndev->mw_bar;
+	bar = ntb_epf_mw_to_bar(ndev, idx);
+	if (bar < 0)
+		return bar;
 
 	if (base)
 		*base = pci_resource_start(ndev->ntb.pdev, bar) + offset;
@@ -560,6 +564,11 @@ static int ntb_epf_init_dev(struct ntb_epf_dev *ndev)
 	ndev->mw_count = readl(ndev->ctrl_reg + NTB_EPF_MW_COUNT);
 	ndev->spad_count = readl(ndev->ctrl_reg + NTB_EPF_SPAD_COUNT);
 
+	if (ndev->mw_count > NTB_EPF_MAX_MW_COUNT) {
+		dev_err(dev, "Unsupported MW count: %u\n", ndev->mw_count);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -596,14 +605,15 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev,
 		dev_warn(&pdev->dev, "Cannot DMA highmem\n");
 	}
 
-	ndev->ctrl_reg = pci_iomap(pdev, ndev->ctrl_reg_bar, 0);
+	ndev->ctrl_reg = pci_iomap(pdev, ndev->barno_map[BAR_CONFIG], 0);
 	if (!ndev->ctrl_reg) {
 		ret = -EIO;
 		goto err_pci_regions;
 	}
 
-	if (ndev->peer_spad_reg_bar) {
-		ndev->peer_spad_reg = pci_iomap(pdev, ndev->peer_spad_reg_bar, 0);
+	if (ndev->barno_map[BAR_PEER_SPAD] != ndev->barno_map[BAR_CONFIG]) {
+		ndev->peer_spad_reg = pci_iomap(pdev,
+						ndev->barno_map[BAR_PEER_SPAD], 0);
 		if (!ndev->peer_spad_reg) {
 			ret = -EIO;
 			goto err_pci_regions;
@@ -614,7 +624,7 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev,
 		ndev->peer_spad_reg = ndev->ctrl_reg + spad_off  + spad_sz;
 	}
 
-	ndev->db_reg = pci_iomap(pdev, ndev->db_reg_bar, 0);
+	ndev->db_reg = pci_iomap(pdev, ndev->barno_map[BAR_DB], 0);
 	if (!ndev->db_reg) {
 		ret = -EIO;
 		goto err_pci_regions;
@@ -659,12 +669,7 @@ static void ntb_epf_cleanup_isr(struct ntb_epf_dev *ndev)
 static int ntb_epf_pci_probe(struct pci_dev *pdev,
 			     const struct pci_device_id *id)
 {
-	enum pci_barno peer_spad_reg_bar = BAR_1;
-	enum pci_barno ctrl_reg_bar = BAR_0;
-	enum pci_barno db_reg_bar = BAR_2;
-	enum pci_barno mw_bar = BAR_2;
 	struct device *dev = &pdev->dev;
-	struct ntb_epf_data *data;
 	struct ntb_epf_dev *ndev;
 	int ret;
 
@@ -675,18 +680,10 @@ static int ntb_epf_pci_probe(struct pci_dev *pdev,
 	if (!ndev)
 		return -ENOMEM;
 
-	data = (struct ntb_epf_data *)id->driver_data;
-	if (data) {
-		peer_spad_reg_bar = data->peer_spad_reg_bar;
-		ctrl_reg_bar = data->ctrl_reg_bar;
-		db_reg_bar = data->db_reg_bar;
-		mw_bar = data->mw_bar;
-	}
+	ndev->barno_map = (const enum pci_barno *)id->driver_data;
+	if (!ndev->barno_map)
+		return -EINVAL;
 
-	ndev->peer_spad_reg_bar = peer_spad_reg_bar;
-	ndev->ctrl_reg_bar = ctrl_reg_bar;
-	ndev->db_reg_bar = db_reg_bar;
-	ndev->mw_bar = mw_bar;
 	ndev->dev = dev;
 
 	ntb_epf_init_struct(ndev, pdev);
@@ -730,30 +727,36 @@ static void ntb_epf_pci_remove(struct pci_dev *pdev)
 	ntb_epf_deinit_pci(ndev);
 }
 
-static const struct ntb_epf_data j721e_data = {
-	.ctrl_reg_bar = BAR_0,
-	.peer_spad_reg_bar = BAR_1,
-	.db_reg_bar = BAR_2,
-	.mw_bar = BAR_2,
+static const enum pci_barno j721e_map[NTB_BAR_NUM] = {
+	[BAR_CONFIG]	= BAR_0,
+	[BAR_PEER_SPAD]	= BAR_1,
+	[BAR_DB]	= BAR_2,
+	[BAR_MW1]	= BAR_2,
+	[BAR_MW2]	= BAR_3,
+	[BAR_MW3]	= BAR_4,
+	[BAR_MW4]	= BAR_5
 };
 
-static const struct ntb_epf_data mx8_data = {
-	.ctrl_reg_bar = BAR_0,
-	.peer_spad_reg_bar = BAR_0,
-	.db_reg_bar = BAR_2,
-	.mw_bar = BAR_4,
+static const enum pci_barno mx8_map[NTB_BAR_NUM] = {
+	[BAR_CONFIG]	= BAR_0,
+	[BAR_PEER_SPAD]	= BAR_0,
+	[BAR_DB]	= BAR_2,
+	[BAR_MW1]	= BAR_4,
+	[BAR_MW2]	= BAR_5,
+	[BAR_MW3]	= NO_BAR,
+	[BAR_MW4]	= NO_BAR
 };
 
 static const struct pci_device_id ntb_epf_pci_tbl[] = {
 	{
 		PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J721E),
 		.class = PCI_CLASS_MEMORY_RAM << 8, .class_mask = 0xffff00,
-		.driver_data = (kernel_ulong_t)&j721e_data,
+		.driver_data = (kernel_ulong_t)j721e_map,
 	},
 	{
 		PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x0809),
 		.class = PCI_CLASS_MEMORY_RAM << 8, .class_mask = 0xffff00,
-		.driver_data = (kernel_ulong_t)&mx8_data,
+		.driver_data = (kernel_ulong_t)mx8_map,
 	},
 	{ },
 };
-- 
2.51.0


  parent reply	other threads:[~2025-10-26 14:50 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-26 14:48 [PATCH AUTOSEL 6.17-5.4] ACPI: property: Return present device nodes only on fwnode interface Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.4] ceph: add checking of wait_for_completion_killable() return value Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.4] 9p: sysfs_init: don't hardcode error to ENOMEM Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.10] um: Fix help message for ssl-non-raw Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17] clk: thead: th1520-ap: set all AXI clocks to CLK_IS_CRITICAL Sasha Levin
2025-10-26 14:48 ` Sasha Levin [this message]
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17] rtc: zynqmp: Restore alarm functionality after kexec transition Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17] hyperv: Add missing field to hv_output_map_device_interrupt Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.4] fbdev: Add bounds checking in bit_putcs to fix vmalloc-out-of-bounds Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17] fbdev: core: Fix ubsan warning in pixel_to_pat Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.10] ASoC: meson: aiu-encoder-i2s: fix bit clock polarity Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.4] fs/hpfs: Fix error code for new_inode() failure in mkdir/create/mknod/symlink Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17] drm/amdgpu: Report individual reset error Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.15] clk: ti: am33xx: keep WKUP_DEBUGSS_CLKCTRL enabled Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17] clk: at91: add ACR in all PLL settings Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-6.12] clk: scmi: Add duty cycle ops only when duty cycle is supported Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.10] ARM: at91: pm: save and restore ACR during PLL disable/enable Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-6.6] rtc: pcf2127: fix watchdog interrupt mask on pcf2131 Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.15] clk: at91: clk-master: Add check for divide by 3 Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-5.15] rtc: pcf2127: clear minute/second interrupt Sasha Levin
2025-10-26 14:48 ` [PATCH AUTOSEL 6.17-6.12] clk: at91: sam9x7: Add peripheral clock id for pmecc Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-5.4] 9p: fix /sys/fs/9p/caches overwriting itself Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.12] 9p/trans_fd: p9_fd_request: kick rx thread if EPOLLIN Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17] clk: samsung: exynos990: Add missing USB clock registers to HSI0 Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17] clocksource: hyper-v: Skip unnecessary checks for the root partition Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.12] ceph: fix multifs mds auth caps issue Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.12] LoongArch: Handle new atomic instructions for probes Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.6] ceph: refactor wake_up_bit() pattern of calling Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.12] drm/amdkfd: Fix mmap write lock not release Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.12] ceph: fix potential race condition in ceph_ioctl_lazyio() Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.12] clk: qcom: gcc-ipq6018: rework nss_port5 clock to multiple conf Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.1] clk: at91: clk-sam9x60-pll: force write to PLL_UPDT register Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-5.4] tools bitmap: Add missing asm-generic/bitsperlong.h include Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17] ALSA: hda/realtek: Add quirk for ASUS ROG Zephyrus Duo Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.1] kbuild: uapi: Strip comments before size type check Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.1] tools: lib: thermal: don't preserve owner in install Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.1] scsi: ufs: core: Include UTP error in INT_FATAL_ERRORS Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.1] clk: sunxi-ng: sun6i-rtc: Add A523 specifics Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.12] clk: scmi: migrate round_rate() to determine_rate() Sasha Levin
2025-10-26 23:16   ` Brian Masney
2025-10-28 17:47     ` Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.12] clk: clocking-wizard: Fix output clock register offset for Versal platforms Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17] ASoC: rt722: add settings for rt722VB Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-5.15] cpufreq: tegra186: Initialize all cores to max frequencies Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.1] tools: lib: thermal: use pkg-config to locate libnl3 Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17] clk: renesas: rzv2h: Re-assert reset on deassert timeout Sasha Levin
2025-10-26 14:49 ` [PATCH AUTOSEL 6.17-6.12] net: wwan: t7xx: add support for HP DRMR-H01 Sasha Levin

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20251026144958.26750-6-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=Frank.Li@nxp.com \
    --cc=alexander.deucher@amd.com \
    --cc=alexandre.f.demers@gmail.com \
    --cc=jbrunet@baylibre.com \
    --cc=jdmason@kudzu.us \
    --cc=patches@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

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

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