[PATCH] nvme-cli: endian swap mmio access
Christoph Hellwig
hch at lst.de
Wed Oct 26 08:01:16 PDT 2016
PCIe is always defined as little endian, so swap the data read from the
register to native endian.
Use the opportunity to also apply the no 64-bit access workaround to
all of the register accesses and not just some and dump struct nvme_reg.
Signed-off-by: Christoph Hellwig <hch at lst.de>
---
nvme.c | 128 +++++++++++++++++++++++++++++++++++------------------------------
nvme.h | 16 ---------
2 files changed, 70 insertions(+), 74 deletions(-)
diff --git a/nvme.c b/nvme.c
index a238b2e..220a57a 100644
--- a/nvme.c
+++ b/nvme.c
@@ -703,7 +703,7 @@ static char *nvme_char_from_block(char *block)
return block;
}
-static void get_registers(struct nvme_bar **bar)
+static void *get_registers(void)
{
int pci_fd;
char *base, path[512];
@@ -726,7 +726,7 @@ static void get_registers(struct nvme_bar **bar)
fprintf(stderr, "%s failed to map\n", base);
exit(ENODEV);
}
- *bar = membase;
+ return membase;
}
static void print_list_item(struct list_item list_item)
@@ -1334,9 +1334,19 @@ static int reset(int argc, char **argv, struct command *cmd, struct plugin *plug
return err;
}
-static void print_lo_hi_64(uint32_t *val)
+static inline uint32_t mmio_read32(void *addr)
{
- printf("%x%08x\n", val[1], val[0]);
+ __le32 *p = addr;
+
+ return le32_to_cpu(*p);
+}
+
+/* Access 64-bit registers as 2 32-bit; Some devices fail 64-bit MMIO. */
+static inline __u64 mmio_read64(void *addr)
+{
+ __le32 *p = addr;
+
+ return le32_to_cpu(*p) | ((uint64_t)le32_to_cpu(*(p + 1)) << 32);
}
static int show_registers(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -1344,7 +1354,9 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu
const char *desc = "Reads and shows the defined NVMe controller registers "\
"in binary or human-readable format";
const char *human_readable = "show info in readable format";
- struct nvme_bar *bar;
+ uint64_t cap, asq, acq;
+ uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc;
+ void *bar;
struct config {
int human_readable;
@@ -1361,71 +1373,71 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu
parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg));
- get_registers(&bar);
+ bar = get_registers();
+ cap = mmio_read64(bar + NVME_REG_CAP);
+ vs = mmio_read32(bar + NVME_REG_VS);
+ intms = mmio_read32(bar + NVME_REG_INTMS);
+ intmc = mmio_read32(bar + NVME_REG_INTMC);
+ cc = mmio_read32(bar + NVME_REG_CC);
+ csts = mmio_read32(bar + NVME_REG_CSTS);
+ nssr = mmio_read32(bar + NVME_REG_NSSR);
+ aqa = mmio_read32(bar + NVME_REG_AQA);
+ asq = mmio_read64(bar + NVME_REG_ASQ);
+ acq = mmio_read64(bar + NVME_REG_ACQ);
+ cmbloc = mmio_read32(bar + NVME_REG_CMBLOC);
+ cmbsz = mmio_read32(bar + NVME_REG_CMBSZ);
if (cfg.human_readable) {
- printf("cap : ");
- print_lo_hi_64((uint32_t *)&bar->cap);
- show_registers_cap((struct nvme_bar_cap *)&bar->cap);
+ printf("cap : %"PRIx64"\n", cap);
+ show_registers_cap((struct nvme_bar_cap *)&cap);
- printf("version : %x\n", bar->vs);
- show_registers_version(bar->vs);
-
- printf("intms : %x\n", bar->intms);
- printf("\tInterrupt Vector Mask Set (IVMS): %x\n\n", bar->intms);
+ printf("version : %x\n", vs);
+ show_registers_version(vs);
+
+ printf("intms : %x\n", intms);
+ printf("\tInterrupt Vector Mask Set (IVMS): %x\n\n", intms);
- printf("intmc : %x\n", bar->intmc);
- printf("\tInterrupt Vector Mask Clear (IVMC): %x\n\n", bar->intmc);
+ printf("intmc : %x\n", intmc);
+ printf("\tInterrupt Vector Mask Clear (IVMC): %x\n\n", intmc);
- printf("cc : %x\n", bar->cc);
- show_registers_cc(bar->cc);
+ printf("cc : %x\n", cc);
+ show_registers_cc(cc);
- printf("csts : %x\n", bar->csts);
- show_registers_csts(bar->csts);
+ printf("csts : %x\n", csts);
+ show_registers_csts(csts);
- printf("nssr : %x\n", bar->nssr);
- printf("\tNVM Subsystem Reset Control (NSSRC): %u\n\n", bar->nssr);
+ printf("nssr : %x\n", nssr);
+ printf("\tNVM Subsystem Reset Control (NSSRC): %u\n\n", nssr);
- printf("aqa : %x\n", bar->aqa);
- show_registers_aqa(bar->aqa);
+ printf("aqa : %x\n", aqa);
+ show_registers_aqa(aqa);
- printf("asq : ");
- print_lo_hi_64((uint32_t *)&bar->asq);
- printf("\tAdmin Submission Queue Base (ASQB): ");
- print_lo_hi_64((uint32_t *)&bar->asq);
- printf("\n");
+ printf("asq : %"PRIx64"\n", asq);
+ printf("\tAdmin Submission Queue Base (ASQB): %"PRIx64"\n",
+ asq);
- printf("acq : ");
- print_lo_hi_64((uint32_t *)&bar->acq);
- printf("\tAdmin Completion Queue Base (ACQB): ");
- print_lo_hi_64((uint32_t *)&bar->acq);
- printf("\n");
+ printf("acq : %"PRIx64"\n", acq);
+ printf("\tAdmin Completion Queue Base (ACQB): %"PRIx64"\n",
+ acq);
- printf("cmbloc : %x\n", bar->cmbloc);
- show_registers_cmbloc(bar->cmbloc, bar->cmbsz);
+ printf("cmbloc : %x\n", cmbloc);
+ show_registers_cmbloc(cmbloc, cmbsz);
- printf("cmbsz : %x\n", bar->cmbsz);
- show_registers_cmbsz(bar->cmbsz);
- }
- else {
- printf("cap : ");
- print_lo_hi_64((uint32_t *)&bar->cap);
-
- printf("version : %x\n", bar->vs);
- printf("intms : %x\n", bar->intms);
- printf("intmc : %x\n", bar->intmc);
- printf("cc : %x\n", bar->cc);
- printf("csts : %x\n", bar->csts);
- printf("nssr : %x\n", bar->nssr);
- printf("aqa : %x\n", bar->aqa);
- printf("asq : ");
- print_lo_hi_64((uint32_t *)&bar->asq);
-
- printf("acq : ");
- print_lo_hi_64((uint32_t *)&bar->acq);
-
- printf("cmbloc : %x\n", bar->cmbloc);
- printf("cmbsz : %x\n", bar->cmbsz);
+ printf("cmbsz : %x\n", cmbsz);
+ show_registers_cmbsz(cmbsz);
+ } else {
+ printf("cap : %"PRIx64"\n", cap);
+ printf("version : %x\n", vs);
+ printf("intms : %x\n", intms);
+ printf("intmc : %x\n", intmc);
+ printf("cc : %x\n", cc);
+ printf("csts : %x\n", csts);
+ printf("nssr : %x\n", nssr);
+ printf("aqa : %x\n", aqa);
+ printf("asq : %"PRIx64"\n", asq);
+ printf("acq : %"PRIx64"\n", acq);
+ printf("cmbloc : %x\n", cmbloc);
+ printf("cmbsz : %x\n", cmbsz);
}
return 0;
diff --git a/nvme.h b/nvme.h
index f53800b..6623505 100644
--- a/nvme.h
+++ b/nvme.h
@@ -109,22 +109,6 @@ struct nvme_controller_list {
__le16 identifier[];
};
-struct nvme_bar {
- __u64 cap; /* Controller Capabilities */
- __u32 vs; /* Version */
- __u32 intms; /* Interrupt Mask Set */
- __u32 intmc; /* Interrupt Mask Clear */
- __u32 cc; /* Controller Configuration */
- __u32 rsvd1; /* Reserved */
- __u32 csts; /* Controller Status */
- __u32 nssr; /* NVM Subsystem Reset */
- __u32 aqa; /* Admin Queue Attributes */
- __u64 asq; /* Admin SQ Base Address */
- __u64 acq; /* Admin CQ Base Address */
- __u32 cmbloc; /* Controller Memory Buffer Location */
- __u32 cmbsz; /* Controller Memory Buffer Size */
-};
-
struct nvme_bar_cap {
__u16 mqes;
__u8 ams_cqr;
--
2.1.4
More information about the Linux-nvme
mailing list