From: Mathias Krause <minipli@grsecurity.net>
To: Justin Tee <justin.tee@broadcom.com>,
Paul Ely <paul.ely@broadcom.com>,
linux-scsi@vger.kernel.org
Cc: Mathias Krause <minipli@grsecurity.net>,
James Smart <jsmart2021@gmail.com>
Subject: [PATCH] scsi: lpfc: Properly set WC for DPP mapping
Date: Tue, 13 Jan 2026 23:27:16 +0100 [thread overview]
Message-ID: <20260113222716.2454544-1-minipli@grsecurity.net> (raw)
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
next reply other threads:[~2026-01-13 22:27 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-13 22:27 Mathias Krause [this message]
2026-01-16 17:46 ` [PATCH] scsi: lpfc: Properly set WC for DPP mapping 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
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=20260113222716.2454544-1-minipli@grsecurity.net \
--to=minipli@grsecurity.net \
--cc=jsmart2021@gmail.com \
--cc=justin.tee@broadcom.com \
--cc=linux-scsi@vger.kernel.org \
--cc=paul.ely@broadcom.com \
/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