@@ -49,6 +49,7 @@ static 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" ;
5151static const char * power_limit_feat = "power limit feature" ;
52+ static const char * power_thresh_feat = "power threshold feature" ;
5253
5354static int feat_get (struct nvme_transport_handle * hdl , const __u8 fid ,
5455 __u32 cdw11 , __u8 sel , __u8 uidx , const char * feat )
@@ -669,3 +670,84 @@ static int feat_power_limit(int argc, char **argv, struct command *acmd,
669670
670671 return err ;
671672}
673+
674+ static int power_thresh_set (struct nvme_transport_handle * hdl , const __u8 fid ,
675+ __u8 ptv , __u8 pts , __u8 pmts , __u8 ept , __u8 uidx ,
676+ bool sv )
677+ {
678+ __u32 cdw11 = NVME_SET (ptv , FEAT_POWER_THRESH_PTV ) |
679+ NVME_SET (pmts , FEAT_POWER_THRESH_PMTS ) |
680+ NVME_SET (pts , FEAT_POWER_THRESH_PTS ) |
681+ NVME_SET (ept , FEAT_POWER_THRESH_EPT );
682+ __u64 result ;
683+ int err ;
684+
685+ err = nvme_set_features (hdl , 0 , fid , sv , cdw11 , 0 , 0 , uidx , 0 , NULL , 0 ,
686+ & result );
687+
688+ nvme_show_init ();
689+
690+ if (err > 0 ) {
691+ nvme_show_status (err );
692+ } else if (err < 0 ) {
693+ nvme_show_perror ("Set %s" , power_thresh_feat );
694+ } else {
695+ nvme_show_result ("Set %s: 0x%04x (%s)" , power_thresh_feat ,
696+ cdw11 , sv ? "Save" : "Not save" );
697+ nvme_feature_show_fields (fid , cdw11 , NULL );
698+ }
699+
700+ nvme_show_finish ();
701+
702+ return err ;
703+ }
704+
705+ static int feat_power_thresh (int argc , char * * argv , struct command * acmd ,
706+ struct plugin * plugin )
707+ {
708+ const char * ptv = "power threshold value" ;
709+ const char * pts = "power threshold scale" ;
710+ const char * pmts = "power measurement type select" ;
711+ const char * ept = "enable power threshold" ;
712+ const __u8 fid = NVME_FEAT_FID_POWER_THRESH ;
713+
714+ _cleanup_nvme_global_ctx_ struct nvme_global_ctx * ctx = NULL ;
715+
716+ _cleanup_nvme_transport_handle_ struct nvme_transport_handle * hdl =
717+ NULL ;
718+ int err ;
719+
720+ struct config {
721+ __u8 ptv ;
722+ __u8 pts ;
723+ __u8 pmts ;
724+ __u8 ept ;
725+ __u8 uidx ;
726+ __u8 sel ;
727+ };
728+
729+ struct config cfg = { 0 };
730+
731+ FEAT_ARGS (opts ,
732+ OPT_BYTE ("ptv" , 'p' , & cfg .ptv , ptv ),
733+ OPT_BYTE ("pts" , 't' , & cfg .pts , pts ),
734+ OPT_BYTE ("pmts" , 'm' , & cfg .pmts , pmts ),
735+ OPT_BYTE ("ept" , 'e' , & cfg .ept , ept ),
736+ OPT_BYTE ("uuid-index" , 'u' , & cfg .uidx , uuid_index ));
737+
738+ err = parse_and_open (& ctx , & hdl , argc , argv , POWER_LIMIT_DESC , opts );
739+ if (err )
740+ return err ;
741+
742+ if (argconfig_parse_seen (opts , "ptv" ) ||
743+ argconfig_parse_seen (opts , "pmts" ) ||
744+ argconfig_parse_seen (opts , "ept" ))
745+ err = power_thresh_set (hdl , fid , cfg .ptv , cfg .pts , cfg .pmts ,
746+ cfg .ept , cfg .uidx ,
747+ argconfig_parse_seen (opts , "save" ));
748+ else
749+ err = feat_get (hdl , fid , 0 , cfg .sel , cfg .uidx ,
750+ power_thresh_feat );
751+
752+ return err ;
753+ }
0 commit comments