Linux SCSI subsystem development
 help / color / mirror / Atom feed
* [PATCH] scsi: lpfc: Properly set WC for DPP mapping
@ 2026-01-13 22:27 Mathias Krause
  2026-01-16 17:46 ` Justin Tee
  0 siblings, 1 reply; 10+ messages in thread
From: Mathias Krause @ 2026-01-13 22:27 UTC (permalink / raw)
  To: Justin Tee, Paul Ely, linux-scsi; +Cc: Mathias Krause, James Smart

Using set_memory_wc() to enable write-combining for the DPP portion of
the MMIO mapping is wrong as set_memory_*() is meant to operate on RAM
only, not MMIO mappings. In fact, as used currently triggers a BUG_ON()
with enabled CONFIG_DEBUG_VIRTUAL.

Simply map the DPP region separately and in addition to the already
existing mappings, avoiding any possible negative side effects for
these.

Fixes: 1351e69fc6db ("scsi: lpfc: Add push-to-adapter support to sli4")
Signed-off-by: Mathias Krause <minipli@grsecurity.net>
Cc: James Smart <jsmart2021@gmail.com>
---
!!! WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!!

I don't have any hardware to test this on. I just got the report from a
customer of ours regarding the CONFIG_DEBUG_VIRTUAL BUG_ON(). As I don't
have any spec for the hardware either, I assumed a few things, like:
1/ DPP regions are only supported on SIL4 devices.
2/ DPP may be shared with other registers (doorbells?) in the same BAR.

That's why I fixed the bug by creating a dedicated mapping for the DPP
region instead of making the existing one ioremap_wc(). I simply
assumed, the fact that 'dpp_offset' needs to be queried instead of
blindly assumed to be zero allows the DPP region to be shared with other
registers that may be harmed by a WC mapping (slow reads, etc.).

Again, as I don't have any hardware, I can't do any performance
benchmarks either but the dedicated mapping should avoid past[1] latency
issues observed.

[1] https://lore.kernel.org/all/e1da721e-8ec4-9e57-9fb2-9141514e8785@gmail.com/

 drivers/scsi/lpfc/lpfc_init.c |  2 ++
 drivers/scsi/lpfc/lpfc_sli.c  | 52 +++++++++++++++++++++++++++++++----
 drivers/scsi/lpfc/lpfc_sli4.h |  3 ++
 3 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b1460b16dd91..c6bb45c3d4c4 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -12034,6 +12034,8 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba)
 		iounmap(phba->sli4_hba.conf_regs_memmap_p);
 		if (phba->sli4_hba.dpp_regs_memmap_p)
 			iounmap(phba->sli4_hba.dpp_regs_memmap_p);
+		if (phba->sli4_hba.dpp_regs_memmap_wc_p)
+			iounmap(phba->sli4_hba.dpp_regs_memmap_wc_p);
 		break;
 	case LPFC_SLI_INTF_IF_TYPE_1:
 		break;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 73d77cfab5f8..76e32891ee20 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -15981,6 +15981,46 @@ lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset)
 	return NULL;
 }
 
+static phys_addr_t
+lpfc_dual_chute_pci_bar_addr(struct lpfc_hba *phba, uint16_t pci_barset)
+{
+	if (!phba->pcidev)
+		return PHYS_ADDR_MAX;
+
+	switch (pci_barset) {
+	case WQ_PCI_BAR_0_AND_1:
+		return phba->pci_bar0_map;
+	case WQ_PCI_BAR_2_AND_3:
+		return phba->pci_bar1_map;
+	case WQ_PCI_BAR_4_AND_5:
+		return phba->pci_bar2_map;
+	default:
+		break;
+	}
+	return PHYS_ADDR_MAX;
+}
+
+static __maybe_unused void __iomem *
+lpfc_dpp_wc_map(struct lpfc_hba *phba, uint16_t pci_barset, uint32_t dpp_offset,
+		uint32_t size)
+{
+	if (!phba->sli4_hba.dpp_regs_memmap_wc_p) {
+		void __iomem *dpp_map;
+		phys_addr_t dpp_addr;
+
+		dpp_addr = lpfc_dual_chute_pci_bar_addr(phba, pci_barset);
+		if (dpp_addr == PHYS_ADDR_MAX)
+			return NULL;
+
+		dpp_addr += dpp_offset;
+		dpp_map = ioremap_wc(dpp_addr, size);
+		if (dpp_map)
+			phba->sli4_hba.dpp_regs_memmap_wc_p = dpp_map;
+	}
+
+	return phba->sli4_hba.dpp_regs_memmap_wc_p;
+}
+
 /**
  * lpfc_modify_hba_eq_delay - Modify Delay Multiplier on EQs
  * @phba: HBA structure that EQs are on.
@@ -16944,9 +16984,6 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
 	uint8_t dpp_barset;
 	uint32_t dpp_offset;
 	uint8_t wq_create_version;
-#ifdef CONFIG_X86
-	unsigned long pg_addr;
-#endif
 
 	/* sanity check on queue memory */
 	if (!wq || !cq)
@@ -17132,14 +17169,17 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
 
 #ifdef CONFIG_X86
 			/* Enable combined writes for DPP aperture */
-			pg_addr = (unsigned long)(wq->dpp_regaddr) & PAGE_MASK;
-			rc = set_memory_wc(pg_addr, 1);
-			if (rc) {
+			bar_memmap_p = lpfc_dpp_wc_map(phba, pci_barset,
+						       dpp_offset,
+						       wq->entry_size);
+			if (!bar_memmap_p) {
 				lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 					"3272 Cannot setup Combined "
 					"Write on WQ[%d] - disable DPP\n",
 					wq->queue_id);
 				phba->cfg_enable_dpp = 0;
+			} else {
+				wq->dpp_regaddr = bar_memmap_p;
 			}
 #else
 			phba->cfg_enable_dpp = 0;
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index fd6dab157887..bcd12b59fa92 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -785,6 +785,9 @@ struct lpfc_sli4_hba {
 	void __iomem *dpp_regs_memmap_p;  /* Kernel memory mapped address for
 					   * dpp registers
 					   */
+	void __iomem *dpp_regs_memmap_wc_p;/* Kernel memory mapped address for
+					   * dpp registers with write combining
+					   */
 	union {
 		struct {
 			/* IF Type 0, BAR 0 PCI cfg space reg mem map */
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-02-12 18:45 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-13 22:27 [PATCH] scsi: lpfc: Properly set WC for DPP mapping Mathias Krause
2026-01-16 17:46 ` Justin Tee
2026-01-16 22:33   ` Justin Tee
2026-01-19 16:45     ` Mathias Krause
2026-01-21  0:44       ` Justin Tee
2026-02-09 18:47         ` Justin Tee
2026-02-11 14:34           ` Mathias Krause
2026-02-12  0:01             ` Justin Tee
2026-02-12  8:03               ` Mathias Krause
2026-02-12 18:43                 ` Justin Tee

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox