@@ -48,9 +48,10 @@ static const char *timestamp_feat = "timestamp feature";
4848static const char * temp_thresh_feat = "temperature threshold feature" ;
4949static const char * arbitration_feat = "arbitration feature" ;
5050static const char * volatile_wc_feat = "volatile write cache feature" ;
51+ static const char * power_limit_feat = "power limit feature" ;
5152
5253static int feat_get (struct nvme_transport_handle * hdl , const __u8 fid ,
53- __u32 cdw11 , __u8 sel , const char * feat )
54+ __u32 cdw11 , __u8 sel , __u8 uidx , const char * feat )
5455{
5556 __u64 result ;
5657 int err ;
@@ -142,9 +143,10 @@ static int feat_power_mgmt(int argc, char **argv, struct command *acmd, struct p
142143 return err ;
143144
144145 if (argconfig_parse_seen (opts , "ps" ))
145- err = power_mgmt_set (hdl , fid , cfg .ps , cfg .wh , argconfig_parse_seen (opts , "save" ));
146+ err = power_mgmt_set (hdl , fid , cfg .ps , cfg .wh ,
147+ argconfig_parse_seen (opts , "save" ));
146148 else
147- err = feat_get (hdl , fid , 0 , cfg .sel , power_mgmt_feat );
149+ err = feat_get (hdl , fid , 0 , cfg .sel , 0 , power_mgmt_feat );
148150
149151 return err ;
150152}
@@ -240,11 +242,13 @@ static int feat_perfc(int argc, char **argv, struct command *acmd, struct plugin
240242
241243 cdw11 = NVME_SET (cfg .attri , FEAT_PERFC_ATTRI ) | NVME_SET (cfg .rvspa , FEAT_PERFC_RVSPA );
242244
243- if (argconfig_parse_seen (opts , "rvspa" ) || argconfig_parse_seen (opts , "r4karl" ) ||
245+ if (argconfig_parse_seen (opts , "rvspa" ) ||
246+ argconfig_parse_seen (opts , "r4karl" ) ||
244247 argconfig_parse_seen (opts , "paid" ))
245- err = perfc_set (hdl , fid , cdw11 , & cfg , argconfig_parse_seen (opts , "save" ));
248+ err = perfc_set (hdl , fid , cdw11 , & cfg ,
249+ argconfig_parse_seen (opts , "save" ));
246250 else
247- err = feat_get (hdl , fid , cdw11 , cfg .sel , perfc_feat );
251+ err = feat_get (hdl , fid , cdw11 , cfg .sel , 0 , perfc_feat );
248252
249253 return err ;
250254}
@@ -301,10 +305,12 @@ static int feat_hctm(int argc, char **argv, struct command *acmd, struct plugin
301305 if (err )
302306 return err ;
303307
304- if (argconfig_parse_seen (opts , "tmt1" ) || argconfig_parse_seen (opts , "tmt2" ))
305- err = hctm_set (hdl , fid , cfg .tmt1 , cfg .tmt2 , argconfig_parse_seen (opts , "save" ));
308+ if (argconfig_parse_seen (opts , "tmt1" ) ||
309+ argconfig_parse_seen (opts , "tmt2" ))
310+ err = hctm_set (hdl , fid , cfg .tmt1 , cfg .tmt2 ,
311+ argconfig_parse_seen (opts , "save" ));
306312 else
307- err = feat_get (hdl , fid , 0 , cfg .sel , hctm_feat );
313+ err = feat_get (hdl , fid , 0 , cfg .sel , 0 , hctm_feat );
308314
309315 return err ;
310316}
@@ -361,9 +367,10 @@ static int feat_timestamp(int argc, char **argv, struct command *acmd, struct pl
361367 return err ;
362368
363369 if (argconfig_parse_seen (opts , "tstmp" ))
364- err = timestamp_set (hdl , fid , cfg .tstmp , argconfig_parse_seen (opts , "save" ));
370+ err = timestamp_set (hdl , fid , cfg .tstmp ,
371+ argconfig_parse_seen (opts , "save" ));
365372 else
366- err = feat_get (hdl , fid , 0 , cfg .sel , timestamp_feat );
373+ err = feat_get (hdl , fid , 0 , cfg .sel , 0 , timestamp_feat );
367374
368375 return err ;
369376}
@@ -443,11 +450,13 @@ static int feat_temp_thresh(int argc, char **argv, struct command *acmd, struct
443450 if (err )
444451 return err ;
445452
446- if (argconfig_parse_seen (opts , "tmpth" ) || argconfig_parse_seen (opts , "tmpthh" ))
453+ if (argconfig_parse_seen (opts , "tmpth" ) ||
454+ argconfig_parse_seen (opts , "tmpthh" ))
447455 err = temp_thresh_set (hdl , fid , opts , & cfg );
448456 else
449457 err = feat_get (hdl , fid , NVME_SET (cfg .tmpsel , FEAT_TT_TMPSEL ) |
450- NVME_SET (cfg .thsel , FEAT_TT_THSEL ), cfg .sel , temp_thresh_feat );
458+ NVME_SET (cfg .thsel , FEAT_TT_THSEL ), cfg .sel , 0 ,
459+ temp_thresh_feat );
451460
452461 return err ;
453462}
@@ -529,7 +538,7 @@ static int feat_arbitration(int argc, char **argv, struct command *acmd, struct
529538 return err ;
530539
531540 if (argc == 2 || argconfig_parse_seen (opts , "sel" ))
532- return feat_get (hdl , fid , 0 , cfg .sel , "arbitration feature" );
541+ return feat_get (hdl , fid , 0 , cfg .sel , 0 , "arbitration feature" );
533542
534543 return arbitration_set (hdl , fid , opts , & cfg );
535544}
@@ -584,9 +593,79 @@ static int feat_volatile_wc(int argc, char **argv, struct command *acmd, struct
584593 return err ;
585594
586595 if (argconfig_parse_seen (opts , "wce" ))
587- err = volatile_wc_set (hdl , fid , cfg .wce , argconfig_parse_seen (opts , "save" ));
596+ err = volatile_wc_set (hdl , fid , cfg .wce ,
597+ argconfig_parse_seen (opts , "save" ));
588598 else
589- err = feat_get (hdl , fid , 0 , cfg .sel , volatile_wc_feat );
599+ err = feat_get (hdl , fid , 0 , cfg .sel , 0 , volatile_wc_feat );
600+
601+ return err ;
602+ }
603+
604+ static int power_limit_set (struct nvme_transport_handle * hdl , const __u8 fid ,
605+ __u8 plv , __u8 pls , __u8 uidx , bool sv )
606+ {
607+ __u32 cdw13 = NVME_SET (plv , FEAT_POWER_LIMIT_PLV ) |
608+ NVME_SET (pls , FEAT_POWER_LIMIT_PLS );
609+ __u64 result ;
610+ int err ;
611+
612+ err = nvme_set_features (hdl , 0 , fid , sv , 0 , 0 , cdw13 , uidx , 0 , NULL , 0 ,
613+ & result );
614+
615+ nvme_show_init ();
616+
617+ if (err > 0 ) {
618+ nvme_show_status (err );
619+ } else if (err < 0 ) {
620+ nvme_show_perror ("Set %s" , power_limit_feat );
621+ } else {
622+ nvme_show_result ("Set %s: 0x%04x (%s)" , power_limit_feat , cdw13 ,
623+ sv ? "Save" : "Not save" );
624+ nvme_feature_show_fields (fid , cdw13 , NULL );
625+ }
626+
627+ nvme_show_finish ();
628+
629+ return err ;
630+ }
631+
632+ static int feat_power_limit (int argc , char * * argv , struct command * acmd ,
633+ struct plugin * plugin )
634+ {
635+ const char * plv = "power limit value" ;
636+ const char * pls = "power limit scale" ;
637+ const __u8 fid = NVME_FEAT_FID_POWER_LIMIT ;
638+
639+ _cleanup_nvme_global_ctx_ struct nvme_global_ctx * ctx = NULL ;
640+
641+ _cleanup_nvme_transport_handle_ struct nvme_transport_handle * hdl =
642+ NULL ;
643+ int err ;
644+
645+ struct config {
646+ __u8 plv ;
647+ __u8 pls ;
648+ __u8 uidx ;
649+ __u8 sel ;
650+ };
651+
652+ struct config cfg = { 0 };
653+
654+ FEAT_ARGS (opts ,
655+ OPT_BYTE ("plv" , 'p' , & cfg .plv , plv ),
656+ OPT_BYTE ("pls" , 'l' , & cfg .pls , pls ),
657+ OPT_BYTE ("uuid-index" , 'u' , & cfg .uidx , uuid_index ));
658+
659+ err = parse_and_open (& ctx , & hdl , argc , argv , POWER_LIMIT_DESC , opts );
660+ if (err )
661+ return err ;
662+
663+ if (argconfig_parse_seen (opts , "plv" ))
664+ err = power_limit_set (hdl , fid , cfg .plv , cfg .pls , cfg .uidx ,
665+ argconfig_parse_seen (opts , "save" ));
666+ else
667+ err = feat_get (hdl , fid , 0 , cfg .sel , cfg .uidx ,
668+ power_limit_feat );
590669
591670 return err ;
592671}
0 commit comments