|
Daniel Wagner |
664dfa |
From: Klaus Jensen <k.jensen@samsung.com>
|
|
Daniel Wagner |
664dfa |
Date: Tue, 13 Dec 2022 09:58:07 +0100
|
|
Daniel Wagner |
664dfa |
Subject: nvme-pci: fix doorbell buffer value endianness
|
|
Daniel Wagner |
664dfa |
Patch-mainline: v6.2-rc2
|
|
Daniel Wagner |
664dfa |
Git-commit: b5f96cb719d8ba220b565ddd3ba4ac0d8bcfb130
|
|
Daniel Wagner |
664dfa |
References: git-fixes
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
When using shadow doorbells, the event index and the doorbell values are
|
|
Daniel Wagner |
664dfa |
written to host memory. Prior to this patch, the values written would
|
|
Daniel Wagner |
664dfa |
erroneously be written in host endianness. This causes trouble on
|
|
Daniel Wagner |
664dfa |
big-endian platforms. Fix this by adding missing endian conversions.
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
This issue was noticed by Guenter while testing various big-endian
|
|
Daniel Wagner |
664dfa |
platforms under QEMU[1]. A similar fix required for hw/nvme in QEMU is
|
|
Daniel Wagner |
664dfa |
up for review as well[2].
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
[1]: https://lore.kernel.org/qemu-devel/20221209110022.GA3396194@roeck-us.net/
|
|
Daniel Wagner |
664dfa |
[2]: https://lore.kernel.org/qemu-devel/20221212114409.34972-4-its@irrelevant.dk/
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
Fixes: f9f38e33389c ("nvme: improve performance for virtual NVMe devices")
|
|
Daniel Wagner |
664dfa |
Reported-by: Guenter Roeck <linux@roeck-us.net>
|
|
Daniel Wagner |
664dfa |
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
|
|
Daniel Wagner |
664dfa |
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
|
Daniel Wagner |
664dfa |
Acked-by: Daniel Wagner <dwagner@suse.de>
|
|
Daniel Wagner |
664dfa |
---
|
|
Daniel Wagner |
664dfa |
drivers/nvme/host/pci.c | 25 +++++++++++++------------
|
|
Daniel Wagner |
664dfa |
1 file changed, 13 insertions(+), 12 deletions(-)
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
--- a/drivers/nvme/host/pci.c
|
|
Daniel Wagner |
664dfa |
+++ b/drivers/nvme/host/pci.c
|
|
Daniel Wagner |
664dfa |
@@ -110,9 +110,9 @@ struct nvme_dev {
|
|
Daniel Wagner |
664dfa |
mempool_t *iod_mempool;
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
/* shadow doorbell buffer support: */
|
|
Daniel Wagner |
664dfa |
- u32 *dbbuf_dbs;
|
|
Daniel Wagner |
664dfa |
+ __le32 *dbbuf_dbs;
|
|
Daniel Wagner |
664dfa |
dma_addr_t dbbuf_dbs_dma_addr;
|
|
Daniel Wagner |
664dfa |
- u32 *dbbuf_eis;
|
|
Daniel Wagner |
664dfa |
+ __le32 *dbbuf_eis;
|
|
Daniel Wagner |
664dfa |
dma_addr_t dbbuf_eis_dma_addr;
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
/* host memory buffer support: */
|
|
Daniel Wagner |
664dfa |
@@ -172,10 +172,10 @@ struct nvme_queue {
|
|
Daniel Wagner |
664dfa |
u16 last_cq_head;
|
|
Daniel Wagner |
664dfa |
u16 qid;
|
|
Daniel Wagner |
664dfa |
u8 cq_phase;
|
|
Daniel Wagner |
664dfa |
- u32 *dbbuf_sq_db;
|
|
Daniel Wagner |
664dfa |
- u32 *dbbuf_cq_db;
|
|
Daniel Wagner |
664dfa |
- u32 *dbbuf_sq_ei;
|
|
Daniel Wagner |
664dfa |
- u32 *dbbuf_cq_ei;
|
|
Daniel Wagner |
664dfa |
+ __le32 *dbbuf_sq_db;
|
|
Daniel Wagner |
664dfa |
+ __le32 *dbbuf_cq_db;
|
|
Daniel Wagner |
664dfa |
+ __le32 *dbbuf_sq_ei;
|
|
Daniel Wagner |
664dfa |
+ __le32 *dbbuf_cq_ei;
|
|
Daniel Wagner |
664dfa |
};
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
/*
|
|
Daniel Wagner |
664dfa |
@@ -301,11 +301,11 @@ static inline int nvme_dbbuf_need_event(
|
|
Daniel Wagner |
664dfa |
}
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
/* Update dbbuf and return true if an MMIO is required */
|
|
Daniel Wagner |
664dfa |
-static bool nvme_dbbuf_update_and_check_event(u16 value, u32 *dbbuf_db,
|
|
Daniel Wagner |
664dfa |
- volatile u32 *dbbuf_ei)
|
|
Daniel Wagner |
664dfa |
+static bool nvme_dbbuf_update_and_check_event(u16 value, __le32 *dbbuf_db,
|
|
Daniel Wagner |
664dfa |
+ volatile __le32 *dbbuf_ei)
|
|
Daniel Wagner |
664dfa |
{
|
|
Daniel Wagner |
664dfa |
if (dbbuf_db) {
|
|
Daniel Wagner |
664dfa |
- u16 old_value;
|
|
Daniel Wagner |
664dfa |
+ u16 old_value, event_idx;
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
/*
|
|
Daniel Wagner |
664dfa |
* Ensure that the queue is written before updating
|
|
Daniel Wagner |
664dfa |
@@ -313,8 +313,8 @@ static bool nvme_dbbuf_update_and_check_
|
|
Daniel Wagner |
664dfa |
*/
|
|
Daniel Wagner |
664dfa |
wmb();
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
- old_value = *dbbuf_db;
|
|
Daniel Wagner |
664dfa |
- *dbbuf_db = value;
|
|
Daniel Wagner |
664dfa |
+ old_value = le32_to_cpu(*dbbuf_db);
|
|
Daniel Wagner |
664dfa |
+ *dbbuf_db = cpu_to_le32(value);
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
/*
|
|
Daniel Wagner |
664dfa |
* Ensure that the doorbell is updated before reading the event
|
|
Daniel Wagner |
664dfa |
@@ -324,7 +324,8 @@ static bool nvme_dbbuf_update_and_check_
|
|
Daniel Wagner |
664dfa |
*/
|
|
Daniel Wagner |
664dfa |
mb();
|
|
Daniel Wagner |
664dfa |
|
|
Daniel Wagner |
664dfa |
- if (!nvme_dbbuf_need_event(*dbbuf_ei, value, old_value))
|
|
Daniel Wagner |
664dfa |
+ event_idx = le32_to_cpu(*dbbuf_ei);
|
|
Daniel Wagner |
664dfa |
+ if (!nvme_dbbuf_need_event(event_idx, value, old_value))
|
|
Daniel Wagner |
664dfa |
return false;
|
|
Daniel Wagner |
664dfa |
}
|
|
Daniel Wagner |
664dfa |
|