88#define CREATE_CMD
99#include "feat-nvme.h"
1010
11+ #define STR (x ) #x
12+ #define TMT (n ) "thermal management temperature " STR(n)
13+
1114struct perfc_config {
1215 __u32 namespace_id ;
1316 __u8 attri ;
@@ -24,6 +27,7 @@ static const char *power_mgmt_feat = "power management feature";
2427static const char * sel = "[0-3]: current/default/saved/supported" ;
2528static const char * save = "Specifies that the controller shall save the attribute" ;
2629static const char * perfc_feat = "performance characteristics feature" ;
30+ static const char * hctm_feat = "host controlled thermal management feature" ;
2731
2832static int power_mgmt_get (struct nvme_dev * dev , const __u8 fid , __u8 sel )
2933{
@@ -258,3 +262,98 @@ static int feat_perfc(int argc, char **argv, struct command *cmd, struct plugin
258262
259263 return err ;
260264}
265+
266+ static int hctm_get (struct nvme_dev * dev , const __u8 fid , __u8 sel )
267+ {
268+ __u32 result ;
269+ int err ;
270+
271+ struct nvme_get_features_args args = {
272+ .args_size = sizeof (args ),
273+ .fd = dev_fd (dev ),
274+ .fid = fid ,
275+ .sel = sel ,
276+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT ,
277+ .result = & result ,
278+ };
279+
280+ err = nvme_get_features (& args );
281+ if (!err ) {
282+ if (NVME_CHECK (sel , GET_FEATURES_SEL , SUPPORTED ))
283+ nvme_show_select_result (fid , result );
284+ else
285+ nvme_feature_show_fields (fid , result , NULL );
286+ } else {
287+ nvme_show_error ("Get %s" , hctm_feat );
288+ }
289+
290+ return err ;
291+ }
292+
293+ static int hctm_set (struct nvme_dev * dev , const __u8 fid , __u16 tmt1 , __u16 tmt2 , bool save )
294+ {
295+ __u32 result ;
296+ int err ;
297+
298+ struct nvme_set_features_args args = {
299+ .args_size = sizeof (args ),
300+ .fd = dev_fd (dev ),
301+ .fid = fid ,
302+ .cdw11 = NVME_SET (tmt1 , FEAT_HCTM_TMT1 ) | NVME_SET (tmt2 , FEAT_HCTM_TMT2 ),
303+ .save = save ,
304+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT ,
305+ .result = & result ,
306+ };
307+
308+ err = nvme_set_features (& args );
309+
310+ nvme_show_init ();
311+
312+ if (err > 0 ) {
313+ nvme_show_status (err );
314+ } else if (err < 0 ) {
315+ nvme_show_perror ("Set %s" , hctm_feat );
316+ } else {
317+ nvme_show_result ("Set %s: 0x%04x (%s)" , hctm_feat , args .cdw11 ,
318+ save ? "Save" : "Not save" );
319+ nvme_feature_show_fields (fid , args .cdw11 , NULL );
320+ }
321+
322+ nvme_show_finish ();
323+
324+ return err ;
325+ }
326+
327+ static int feat_hctm (int argc , char * * argv , struct command * cmd , struct plugin * plugin )
328+ {
329+ const __u8 fid = NVME_FEAT_FID_HCTM ;
330+
331+ _cleanup_nvme_dev_ struct nvme_dev * dev = NULL ;
332+ int err ;
333+
334+ struct config {
335+ __u16 tmt1 ;
336+ __u16 tmt2 ;
337+ bool save ;
338+ __u8 sel ;
339+ };
340+
341+ struct config cfg = { 0 };
342+
343+ NVME_ARGS (opts ,
344+ OPT_SHRT ("tmt1" , 't' , & cfg .tmt1 , TMT (1 )),
345+ OPT_SHRT ("tmt2" , 'T' , & cfg .tmt2 , TMT (2 )),
346+ OPT_FLAG ("save" , 's' , & cfg .save , save ),
347+ OPT_BYTE ("sel" , 'S' , & cfg .sel , sel ));
348+
349+ err = parse_and_open (& dev , argc , argv , HCTM_DESC , opts );
350+ if (err )
351+ return err ;
352+
353+ if (argconfig_parse_seen (opts , "tmt1" ) || argconfig_parse_seen (opts , "tmt2" ))
354+ err = hctm_set (dev , fid , cfg .tmt1 , cfg .tmt2 , cfg .save );
355+ else
356+ err = hctm_get (dev , fid , cfg .sel );
357+
358+ return err ;
359+ }
0 commit comments