@@ -551,3 +551,99 @@ static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plu
551551
552552 return err ;
553553}
554+
555+ static int fdp_feature (int argc , char * * argv , struct command * cmd , struct plugin * plugin )
556+ {
557+ const char * desc = "Show, enable or disable FDP configuration" ;
558+ const char * enable_conf_idx = "FDP configuration index to enable" ;
559+ const char * endurance_group = "Endurance group ID" ;
560+ const char * disable = "Disable current FDP configuration" ;
561+
562+ _cleanup_nvme_dev_ struct nvme_dev * dev = NULL ;
563+ int err = -1 ;
564+ __u32 result ;
565+ bool enabling_conf_idx = false;
566+ struct nvme_set_features_args setf_args = {
567+ .args_size = sizeof (setf_args ),
568+ .fd = -1 ,
569+ .fid = NVME_FEAT_FID_FDP ,
570+ .save = 1 ,
571+ .nsid = NVME_NSID_ALL ,
572+ .data_len = 0 ,
573+ .data = NULL ,
574+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT ,
575+ };
576+
577+ struct config {
578+ bool disable ;
579+ __u8 fdpcidx ;
580+ __u16 endgid ;
581+ };
582+
583+ struct config cfg = {
584+ .disable = false,
585+ .fdpcidx = 0 ,
586+ .endgid = 0 ,
587+ };
588+
589+ OPT_ARGS (opts ) = {
590+ OPT_SHRT ("endgrp-id" , 'e' , & cfg .endgid , endurance_group ),
591+ OPT_BYTE ("enable-conf-idx" , 'c' , & cfg .fdpcidx , enable_conf_idx ),
592+ OPT_FLAG ("disable" , 'd' , & cfg .disable , disable ),
593+ OPT_INCR ("verbose" , 'v' , & nvme_cfg .verbose , verbose ),
594+ OPT_END ()
595+ };
596+
597+ err = parse_and_open (& dev , argc , argv , desc , opts );
598+ if (err )
599+ return err ;
600+
601+ enabling_conf_idx = argconfig_parse_seen (opts , "enable-conf-idx" );
602+ if (enabling_conf_idx && cfg .disable ) {
603+ nvme_show_error ("Cannot enable and disable at the same time" );
604+ return - EINVAL ;
605+ }
606+
607+ if (!enabling_conf_idx && !cfg .disable ) {
608+ struct nvme_get_features_args getf_args = {
609+ .args_size = sizeof (getf_args ),
610+ .fd = dev_fd (dev ),
611+ .fid = NVME_FEAT_FID_FDP ,
612+ .nsid = NVME_NSID_ALL ,
613+ .sel = NVME_GET_FEATURES_SEL_CURRENT ,
614+ .cdw11 = cfg .endgid ,
615+ .uuidx = 0 ,
616+ .data_len = 0 ,
617+ .data = NULL ,
618+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT ,
619+ .result = & result ,
620+ };
621+
622+ nvme_show_result ("Endurance Group : %d" , cfg .endgid );
623+
624+ err = nvme_get_features (& getf_args );
625+ if (err ) {
626+ nvme_show_status (err );
627+ return err ;
628+ }
629+
630+ nvme_show_result ("Flexible Direct Placement Enable (FDPE) : %s" ,
631+ (result & 0x1 ) ? "Yes" : "No" );
632+ nvme_show_result ("Flexible Direct Placement Configuration Index : %u" ,
633+ (result >> 8 ) & 0xf );
634+ return err ;
635+ }
636+
637+ setf_args .fd = dev_fd (dev );
638+ setf_args .cdw11 = cfg .endgid ;
639+ setf_args .cdw12 = cfg .fdpcidx << 8 | (!cfg .disable );
640+
641+ err = nvme_set_features (& setf_args );
642+ if (err ) {
643+ nvme_show_status (err );
644+ return err ;
645+ }
646+ nvme_show_result ("Success %s Endurance Group: %d, FDP configuration index: %d" ,
647+ (cfg .disable ) ? "disabling" : "enabling" , cfg .endgid , cfg .fdpcidx );
648+ return err ;
649+ }
0 commit comments