@@ -5214,14 +5214,15 @@ static int nvme_get_properties(int fd, void **pbar)
5214
5214
return err ;
5215
5215
}
5216
5216
5217
- static void * mmap_registers (nvme_root_t r , struct nvme_dev * dev )
5217
+ static void * mmap_registers_prot (nvme_root_t r , struct nvme_dev * dev , int prot )
5218
5218
{
5219
5219
nvme_ctrl_t c = NULL ;
5220
5220
nvme_ns_t n = NULL ;
5221
5221
5222
5222
char path [512 ];
5223
5223
void * membase ;
5224
5224
int fd ;
5225
+ int flags = prot | PROT_WRITE ? O_RDWR : O_RDONLY ;
5225
5226
5226
5227
c = nvme_scan_ctrl (r , dev -> name );
5227
5228
if (c ) {
@@ -5239,15 +5240,15 @@ static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev)
5239
5240
nvme_free_ns (n );
5240
5241
}
5241
5242
5242
- fd = open (path , O_RDONLY );
5243
+ fd = open (path , flags );
5243
5244
if (fd < 0 ) {
5244
5245
if (map_log_level (0 , false) >= LOG_DEBUG )
5245
5246
nvme_show_error ("%s did not find a pci resource, open failed %s" ,
5246
5247
dev -> name , strerror (errno ));
5247
5248
return NULL ;
5248
5249
}
5249
5250
5250
- membase = mmap (NULL , getpagesize (), PROT_READ , MAP_SHARED , fd , 0 );
5251
+ membase = mmap (NULL , getpagesize (), prot , MAP_SHARED , fd , 0 );
5251
5252
if (membase == MAP_FAILED ) {
5252
5253
if (map_log_level (0 , false) >= LOG_DEBUG ) {
5253
5254
fprintf (stderr , "%s failed to map. " , dev -> name );
@@ -5260,6 +5261,11 @@ static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev)
5260
5261
return membase ;
5261
5262
}
5262
5263
5264
+ static void * mmap_registers (nvme_root_t r , struct nvme_dev * dev )
5265
+ {
5266
+ return mmap_registers_prot (r , dev , PROT_READ );
5267
+ }
5268
+
5263
5269
static int show_registers (int argc , char * * argv , struct command * cmd , struct plugin * plugin )
5264
5270
{
5265
5271
const char * desc = "Reads and shows the defined NVMe controller registers\n"
@@ -5393,6 +5399,7 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi
5393
5399
r = nvme_scan (NULL );
5394
5400
bar = mmap_registers (r , dev );
5395
5401
if (!bar ) {
5402
+ err = - errno ;
5396
5403
err = nvme_get_properties (dev_fd (dev ), & bar );
5397
5404
if (err )
5398
5405
goto free_tree ;
@@ -5409,6 +5416,72 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi
5409
5416
return err ;
5410
5417
}
5411
5418
5419
+ static void nvme_set_register (void * bar , int offset , uint64_t value )
5420
+ {
5421
+ if (nvme_is_64bit_reg (offset ))
5422
+ mmio_write64 (bar + offset , value );
5423
+ else
5424
+ mmio_write32 (bar + offset , value );
5425
+ }
5426
+
5427
+ static int set_register (int argc , char * * argv , struct command * cmd , struct plugin * plugin )
5428
+ {
5429
+ const char * desc =
5430
+ "Writes and shows the defined NVMe controller register" ;
5431
+ const char * offset = "the offset of the register" ;
5432
+ const char * value = "the value of the register to be set" ;
5433
+
5434
+ _cleanup_nvme_dev_ struct nvme_dev * dev = NULL ;
5435
+ int err ;
5436
+ nvme_root_t r ;
5437
+ void * bar ;
5438
+
5439
+ struct config {
5440
+ int offset ;
5441
+ uint64_t value ;
5442
+ };
5443
+
5444
+ struct config cfg = {
5445
+ .offset = -1 ,
5446
+ .value = 0 ,
5447
+ };
5448
+
5449
+ NVME_ARGS (opts , cfg ,
5450
+ OPT_UINT ("offset" , 'O' , & cfg .offset , offset ),
5451
+ OPT_SUFFIX ("value" , 'V' , & cfg .value , value ));
5452
+
5453
+ err = parse_and_open (& dev , argc , argv , desc , opts );
5454
+ if (err )
5455
+ return err ;
5456
+
5457
+ if (!argconfig_parse_seen (opts , "offset" )) {
5458
+ nvme_show_error ("offset required param" );
5459
+ return - EINVAL ;
5460
+ }
5461
+
5462
+ if (!argconfig_parse_seen (opts , "value" )) {
5463
+ nvme_show_error ("value required param" );
5464
+ return - EINVAL ;
5465
+ }
5466
+
5467
+ r = nvme_scan (NULL );
5468
+ bar = mmap_registers_prot (r , dev , PROT_READ | PROT_WRITE );
5469
+ if (!bar ) {
5470
+ nvme_show_error ("Failed to map" );
5471
+ return - EINVAL ;
5472
+ }
5473
+
5474
+ nvme_set_register (bar , cfg .offset , cfg .value );
5475
+
5476
+ printf ("set-register: %02x (%s), value: %" PRIx64 "\n" , cfg .offset ,
5477
+ nvme_register_to_string (cfg .offset ), cfg .value );
5478
+
5479
+ munmap (bar , getpagesize ());
5480
+ nvme_free_tree (r );
5481
+
5482
+ return err ;
5483
+ }
5484
+
5412
5485
static int get_property (int argc , char * * argv , struct command * cmd , struct plugin * plugin )
5413
5486
{
5414
5487
const char * desc = "Reads and shows the defined NVMe controller property\n"
0 commit comments