@@ -41,6 +41,12 @@ struct arbitration_config {
4141 __u8 sel ;
4242};
4343
44+ struct err_recovery_config {
45+ __u8 tler ;
46+ __u8 dulbe ;
47+ __u8 sel ;
48+ };
49+
4450static const char * power_mgmt_feat = "power management feature" ;
4551static const char * sel = "[0-3]: current/default/saved/supported" ;
4652static const char * save = "Specifies that the controller shall save the attribute" ;
@@ -53,9 +59,11 @@ static const char *volatile_wc_feat = "volatile write cache feature";
5359static const char * power_limit_feat = "power limit feature" ;
5460static const char * power_thresh_feat = "power threshold feature" ;
5561static const char * power_meas_feat = "power measurement feature" ;
62+ static const char * err_recovery_feat = "error recovery feature" ;
5663
57- static int feat_get (struct nvme_transport_handle * hdl , const __u8 fid ,
58- __u32 cdw11 , __u8 sel , __u8 uidx , const char * feat )
64+ static int feat_get_nsid (struct nvme_transport_handle * hdl , __u32 nsid ,
65+ const __u8 fid , __u32 cdw11 , __u8 sel , __u8 uidx ,
66+ const char * feat )
5967{
6068 __u64 result ;
6169 int err ;
@@ -72,7 +80,7 @@ static int feat_get(struct nvme_transport_handle *hdl, const __u8 fid,
7280 return - ENOMEM ;
7381 }
7482
75- err = nvme_get_features (hdl , 0 , fid , sel , cdw11 , uidx , buf , len ,
83+ err = nvme_get_features (hdl , nsid , fid , sel , cdw11 , uidx , buf , len ,
7684 & result );
7785
7886 nvme_show_init ();
@@ -94,6 +102,12 @@ static int feat_get(struct nvme_transport_handle *hdl, const __u8 fid,
94102 return err ;
95103}
96104
105+ static int feat_get (struct nvme_transport_handle * hdl , const __u8 fid ,
106+ __u32 cdw11 , __u8 sel , __u8 uidx , const char * feat )
107+ {
108+ return feat_get_nsid (hdl , 0 , fid , cdw11 , sel , uidx , feat );
109+ }
110+
97111static int power_mgmt_set (struct nvme_transport_handle * hdl , const __u8 fid ,
98112 __u8 ps , __u8 wh , bool sv )
99113{
@@ -831,3 +845,74 @@ static int feat_power_meas(int argc, char **argv, struct command *cmd,
831845
832846 return err ;
833847}
848+
849+ static int err_recovery_set (struct nvme_transport_handle * hdl , const __u8 fid ,
850+ __u32 nsid , __u16 tler , bool dulbe , bool sv )
851+ {
852+ __u32 cdw11 = NVME_SET (tler , FEAT_ERROR_RECOVERY_TLER ) |
853+ NVME_SET (dulbe , FEAT_ERROR_RECOVERY_DULBE );
854+ __u64 result ;
855+ int err ;
856+
857+ err = nvme_set_features (hdl , nsid , fid , sv , cdw11 , 0 , 0 , 0 , 0 , NULL , 0 ,
858+ & result );
859+
860+ nvme_show_init ();
861+
862+ if (err > 0 ) {
863+ nvme_show_status (err );
864+ } else if (err < 0 ) {
865+ nvme_show_perror ("Set %s" , err_recovery_feat );
866+ } else {
867+ nvme_show_result ("Set %s: 0x%04x (%s)" , err_recovery_feat ,
868+ cdw11 , sv ? "Save" : "Not save" );
869+ nvme_feature_show_fields (fid , cdw11 , NULL );
870+ }
871+
872+ nvme_show_finish ();
873+
874+ return err ;
875+ }
876+
877+ static int feat_err_recovery (int argc , char * * argv , struct command * acmd ,
878+ struct plugin * plugin )
879+ {
880+ _cleanup_nvme_transport_handle_ struct nvme_transport_handle * hdl =
881+ NULL ;
882+ _cleanup_nvme_global_ctx_ struct nvme_global_ctx * ctx = NULL ;
883+
884+ const char * dulbe =
885+ "deallocated or unwritten logical block error enable" ;
886+ const char * tler = "time limited error recovery" ;
887+ const __u8 fid = NVME_FEAT_FID_ERR_RECOVERY ;
888+
889+ int err ;
890+
891+ struct config {
892+ __u32 nsid ;
893+ __u16 tler ;
894+ bool dulbe ;
895+ __u8 sel ;
896+ };
897+
898+ struct config cfg = { 0 };
899+
900+ FEAT_ARGS (opts ,
901+ OPT_UINT ("nsid" , 'n' , & cfg .nsid , namespace_id_desired ),
902+ OPT_SHRT ("tler" , 't' , & cfg .tler , tler ),
903+ OPT_FLAG ("dulbe" , 'd' , & cfg .dulbe , dulbe ));
904+
905+ err = parse_and_open (& ctx , & hdl , argc , argv , ERR_RECOVERY_DESC , opts );
906+ if (err )
907+ return err ;
908+
909+ if (argconfig_parse_seen (opts , "tler" ) ||
910+ argconfig_parse_seen (opts , "dulbe" ))
911+ err = err_recovery_set (hdl , fid , cfg .nsid , cfg .tler , cfg .dulbe ,
912+ argconfig_parse_seen (opts , "save" ));
913+ else
914+ err = feat_get_nsid (hdl , cfg .nsid , fid , 0 , cfg .sel , 0 ,
915+ err_recovery_feat );
916+
917+ return err ;
918+ }
0 commit comments