@@ -187,7 +187,7 @@ static const char space[51] = {[0 ... 49] = ' ', '\0'};
187
187
188
188
static char * output_format_val = "normal" ;
189
189
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 );
191
191
192
192
const char * nvme_strerror (int errnum )
193
193
{
@@ -1011,7 +1011,7 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl
1011
1011
__u64 cap ;
1012
1012
1013
1013
r = nvme_scan (NULL );
1014
- bar = mmap_registers (r , dev );
1014
+ bar = mmap_registers (r , dev , false );
1015
1015
nvme_free_tree (r );
1016
1016
1017
1017
if (bar ) {
@@ -5214,14 +5214,18 @@ 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 (nvme_root_t r , struct nvme_dev * dev , bool writable )
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 prot = PROT_READ ;
5226
+
5227
+ if (writable )
5228
+ prot |= PROT_WRITE ;
5225
5229
5226
5230
c = nvme_scan_ctrl (r , dev -> name );
5227
5231
if (c ) {
@@ -5239,15 +5243,15 @@ static void *mmap_registers(nvme_root_t r, struct nvme_dev *dev)
5239
5243
nvme_free_ns (n );
5240
5244
}
5241
5245
5242
- fd = open (path , O_RDONLY );
5246
+ fd = open (path , writable ? O_RDWR : O_RDONLY );
5243
5247
if (fd < 0 ) {
5244
5248
if (map_log_level (0 , false) >= LOG_DEBUG )
5245
5249
nvme_show_error ("%s did not find a pci resource, open failed %s" ,
5246
5250
dev -> name , strerror (errno ));
5247
5251
return NULL ;
5248
5252
}
5249
5253
5250
- membase = mmap (NULL , getpagesize (), PROT_READ , MAP_SHARED , fd , 0 );
5254
+ membase = mmap (NULL , getpagesize (), prot , MAP_SHARED , fd , 0 );
5251
5255
if (membase == MAP_FAILED ) {
5252
5256
if (map_log_level (0 , false) >= LOG_DEBUG ) {
5253
5257
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
5299
5303
flags |= VERBOSE ;
5300
5304
5301
5305
r = nvme_scan (NULL );
5302
- bar = mmap_registers (r , dev );
5306
+ bar = mmap_registers (r , dev , false );
5303
5307
if (!bar ) {
5304
5308
err = nvme_get_properties (dev_fd (dev ), & bar );
5305
5309
if (err )
@@ -5391,7 +5395,7 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi
5391
5395
flags |= VERBOSE ;
5392
5396
5393
5397
r = nvme_scan (NULL );
5394
- bar = mmap_registers (r , dev );
5398
+ bar = mmap_registers (r , dev , false );
5395
5399
if (!bar ) {
5396
5400
err = nvme_get_properties (dev_fd (dev ), & bar );
5397
5401
if (err )
@@ -5409,6 +5413,72 @@ static int get_register(int argc, char **argv, struct command *cmd, struct plugi
5409
5413
return err ;
5410
5414
}
5411
5415
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
+
5412
5482
static int get_property (int argc , char * * argv , struct command * cmd , struct plugin * plugin )
5413
5483
{
5414
5484
const char * desc = "Reads and shows the defined NVMe controller property\n"
0 commit comments