Skip to content

Commit 9e92a28

Browse files
committed
nvme: Add support for set-reg command to write nvme register
Note: For fabrics properties not supported to set by the command. Signed-off-by: Tokunori Ikegami <ikegami.t@gmail.com>
1 parent c351f03 commit 9e92a28

File tree

3 files changed

+95
-7
lines changed

3 files changed

+95
-7
lines changed

common.h

+17
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,21 @@ static inline uint64_t mmio_read64(void *addr)
3535
return ((uint64_t)high << 32) | low;
3636
}
3737

38+
static inline void mmio_write32(void *addr, uint32_t value)
39+
{
40+
leint32_t *p = addr;
41+
42+
*p = cpu_to_le32(value);
43+
}
44+
45+
/* Access 64-bit registers as 2 32-bit; Some devices fail 64-bit MMIO. */
46+
static inline void mmio_write64(void *addr, uint64_t value)
47+
{
48+
uint32_t *p = addr;
49+
uint32_t low = value;
50+
uint32_t high = value >> 32;
51+
52+
*p = cpu_to_le32(low);
53+
*(p + 1) = cpu_to_le32(high);
54+
}
3855
#endif

nvme-builtin.h

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ COMMAND_LIST(
8989
ENTRY("subsystem-reset", "Resets the subsystem", subsystem_reset)
9090
ENTRY("ns-rescan", "Rescans the NVME namespaces", ns_rescan)
9191
ENTRY("show-regs", "Shows the controller registers or properties. Requires character device", show_registers)
92+
ENTRY("set-reg", "Set a register and show the resulting value", set_register)
9293
ENTRY("get-reg", "Get a register and show the resulting value", get_register)
9394
ENTRY("discover", "Discover NVMeoF subsystems", discover_cmd)
9495
ENTRY("connect-all", "Discover and Connect to NVMeoF subsystems", connect_all_cmd)

nvme.c

+77-7
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ static const char space[51] = {[0 ... 49] = ' ', '\0'};
187187

188188
static char *output_format_val = "normal";
189189

190-
static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev);
190+
static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev, bool writable);
191191

192192
const char *nvme_strerror(int errnum)
193193
{
@@ -1011,7 +1011,7 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl
10111011
__u64 cap;
10121012

10131013
r = nvme_scan(NULL);
1014-
bar = mmap_registers(r, dev);
1014+
bar = mmap_registers(r, dev, false);
10151015
nvme_free_tree(r);
10161016

10171017
if (bar) {
@@ -5214,14 +5214,18 @@ static int nvme_get_properties(int fd, void **pbar)
52145214
return err;
52155215
}
52165216

5217-
static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev)
5217+
static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev, bool writable)
52185218
{
52195219
nvme_ctrl_t c = NULL;
52205220
nvme_ns_t n = NULL;
52215221

52225222
char path[512];
52235223
void *membase;
52245224
int fd;
5225+
int prot = PROT_READ;
5226+
5227+
if (writable)
5228+
prot |= PROT_WRITE;
52255229

52265230
c = nvme_scan_ctrl(r, dev->name);
52275231
if (c) {
@@ -5239,15 +5243,15 @@ static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev)
52395243
nvme_free_ns(n);
52405244
}
52415245

5242-
fd = open(path, O_RDONLY);
5246+
fd = open(path, writable ? O_RDWR : O_RDONLY);
52435247
if (fd < 0) {
52445248
if (map_log_level(0, false) >= LOG_DEBUG)
52455249
nvme_show_error("%s did not find a pci resource, open failed %s",
52465250
dev->name, strerror(errno));
52475251
return NULL;
52485252
}
52495253

5250-
membase = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0);
5254+
membase = mmap(NULL, getpagesize(), prot, MAP_SHARED, fd, 0);
52515255
if (membase == MAP_FAILED) {
52525256
if (map_log_level(0, false) >= LOG_DEBUG) {
52535257
fprintf(stderr, "%s failed to map. ", dev->name);
@@ -5299,7 +5303,7 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu
52995303
flags |= VERBOSE;
53005304

53015305
r = nvme_scan(NULL);
5302-
bar = mmap_registers(r, dev);
5306+
bar = mmap_registers(r, dev, false);
53035307
if (!bar) {
53045308
err = nvme_get_properties(dev_fd(dev), &bar);
53055309
if (err)
@@ -5391,7 +5395,7 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi
53915395
flags |= VERBOSE;
53925396

53935397
r = nvme_scan(NULL);
5394-
bar = mmap_registers(r, dev);
5398+
bar = mmap_registers(r, dev, false);
53955399
if (!bar) {
53965400
err = nvme_get_properties(dev_fd(dev), &bar);
53975401
if (err)
@@ -5409,6 +5413,72 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi
54095413
return err;
54105414
}
54115415

5416+
static void nvme_set_register(void *bar, int offset, uint64_t value)
5417+
{
5418+
if (nvme_is_64bit_reg(offset))
5419+
mmio_write64(bar + offset, value);
5420+
else
5421+
mmio_write32(bar + offset, value);
5422+
}
5423+
5424+
static int set_register(int argc, char **argv, struct command *cmd, struct plugin *plugin)
5425+
{
5426+
const char *desc =
5427+
"Writes and shows the defined NVMe controller register";
5428+
const char *offset = "the offset of the register";
5429+
const char *value = "the value of the register to be set";
5430+
5431+
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
5432+
int err;
5433+
nvme_root_t r;
5434+
void *bar;
5435+
5436+
struct config {
5437+
int offset;
5438+
uint64_t value;
5439+
};
5440+
5441+
struct config cfg = {
5442+
.offset = -1,
5443+
.value = 0,
5444+
};
5445+
5446+
NVME_ARGS(opts, cfg,
5447+
OPT_UINT("offset", 'O', &cfg.offset, offset),
5448+
OPT_SUFFIX("value", 'V', &cfg.value, value));
5449+
5450+
err = parse_and_open(&dev, argc, argv, desc, opts);
5451+
if (err)
5452+
return err;
5453+
5454+
if (!argconfig_parse_seen(opts, "offset")) {
5455+
nvme_show_error("offset required param");
5456+
return -EINVAL;
5457+
}
5458+
5459+
if (!argconfig_parse_seen(opts, "value")) {
5460+
nvme_show_error("value required param");
5461+
return -EINVAL;
5462+
}
5463+
5464+
r = nvme_scan(NULL);
5465+
bar = mmap_registers(r, dev, true);
5466+
if (!bar) {
5467+
nvme_show_error("Failed to map");
5468+
return -EINVAL;
5469+
}
5470+
5471+
nvme_set_register(bar, cfg.offset, cfg.value);
5472+
5473+
printf("set-register: %02x (%s), value: %"PRIx64"\n", cfg.offset,
5474+
nvme_register_to_string(cfg.offset), cfg.value);
5475+
5476+
munmap(bar, getpagesize());
5477+
nvme_free_tree(r);
5478+
5479+
return err;
5480+
}
5481+
54125482
static int get_property(int argc, char **argv, struct command *cmd, struct plugin *plugin)
54135483
{
54145484
const char *desc = "Reads and shows the defined NVMe controller property\n"

0 commit comments

Comments
 (0)