@@ -195,6 +195,7 @@ static const char *type = "Error injection type";
195195static const char * nrtdp = "Number of reads to trigger device panic" ;
196196static const char * save = "Specifies that the controller shall save the attribute" ;
197197static const char * enable_ieee1667_silo = "enable IEEE1667 silo" ;
198+ static const char * raw_use = "use binary output" ;
198199
199200static int get_c3_log_page (struct nvme_transport_handle * hdl , char * format )
200201{
@@ -2974,3 +2975,125 @@ static int hwcomp_log(int argc, char **argv, struct command *acmd, struct plugin
29742975{
29752976 return ocp_hwcomp_log (argc , argv , acmd , plugin );
29762977}
2978+
2979+ static int ocp_get_persistent_event_log (int argc , char * * argv ,
2980+ struct command * command , struct plugin * plugin )
2981+ {
2982+ const char * desc = "Retrieve Persistent Event log info for the given " \
2983+ "device in either decoded format(default), json or binary." ;
2984+ const char * action = "action the controller shall take during " \
2985+ "processing this persistent log page command." ;
2986+ const char * log_len = "number of bytes to retrieve" ;
2987+
2988+ _cleanup_free_ struct nvme_persistent_event_log * pevent = NULL ;
2989+ struct nvme_persistent_event_log * pevent_collected = NULL ;
2990+ _cleanup_huge_ struct nvme_mem_huge mh = { 0 , };
2991+ _cleanup_nvme_global_ctx_ struct nvme_global_ctx * ctx = NULL ;
2992+ _cleanup_nvme_transport_handle_ struct nvme_transport_handle * hdl = NULL ;
2993+
2994+ nvme_print_flags_t flags ;
2995+ void * pevent_log_info ;
2996+ int err ;
2997+
2998+ struct config {
2999+ __u8 action ;
3000+ __u32 log_len ;
3001+ bool raw_binary ;
3002+ };
3003+
3004+ struct config cfg = {
3005+ .action = 0xff ,
3006+ .log_len = 0 ,
3007+ .raw_binary = false,
3008+ };
3009+
3010+ NVME_ARGS (opts ,
3011+ OPT_BYTE ("action" , 'a' , & cfg .action , action ),
3012+ OPT_UINT ("log_len" , 'l' , & cfg .log_len , log_len ),
3013+ OPT_FLAG ("raw-binary" , 'b' , & cfg .raw_binary , raw_use ));
3014+
3015+ err = parse_and_open (& ctx , & hdl , argc , argv , desc , opts );
3016+ if (err )
3017+ return err ;
3018+
3019+ err = validate_output_format (nvme_cfg .output_format , & flags );
3020+ if (err < 0 ) {
3021+ nvme_show_error ("Invalid output format" );
3022+ return err ;
3023+ }
3024+
3025+ if (cfg .raw_binary )
3026+ flags = BINARY ;
3027+
3028+ pevent = nvme_alloc (sizeof (* pevent ));
3029+ if (!pevent )
3030+ return - ENOMEM ;
3031+
3032+ err = nvme_get_log_persistent_event (hdl , cfg .action ,
3033+ pevent , sizeof (* pevent ));
3034+ if (err < 0 ) {
3035+ nvme_show_error ("persistent event log: %s" , nvme_strerror (err ));
3036+ return err ;
3037+ } else if (err ) {
3038+ nvme_show_status (err );
3039+ return err ;
3040+ }
3041+
3042+ if (cfg .action == NVME_PEVENT_LOG_RELEASE_CTX ) {
3043+ printf ("Releasing Persistent Event Log Context\n" );
3044+ return 0 ;
3045+ }
3046+
3047+ if (!cfg .log_len && cfg .action != NVME_PEVENT_LOG_EST_CTX_AND_READ ) {
3048+ cfg .log_len = le64_to_cpu (pevent -> tll );
3049+ } else if (!cfg .log_len && cfg .action == NVME_PEVENT_LOG_EST_CTX_AND_READ ) {
3050+ printf ("Establishing Persistent Event Log Context\n" );
3051+ return 0 ;
3052+ }
3053+
3054+ /*
3055+ * if header already read with context establish action 0x1,
3056+ * action shall not be 0x1 again in the subsequent request,
3057+ * until the current context is released by issuing action
3058+ * with 0x2, otherwise throws command sequence error, make
3059+ * it as zero to read the log page
3060+ */
3061+ if (cfg .action == NVME_PEVENT_LOG_EST_CTX_AND_READ )
3062+ cfg .action = NVME_PEVENT_LOG_READ ;
3063+
3064+ pevent_log_info = nvme_alloc_huge (cfg .log_len , & mh );
3065+ if (!pevent_log_info ) {
3066+ nvme_show_error ("failed to allocate huge memory" );
3067+ return - ENOMEM ;
3068+ }
3069+
3070+ err = nvme_get_log_persistent_event (hdl , cfg .action ,
3071+ pevent_log_info , cfg .log_len );
3072+ if (!err ) {
3073+ err = nvme_get_log_persistent_event (hdl , cfg .action ,
3074+ pevent ,
3075+ sizeof (* pevent ));
3076+ if (err < 0 ) {
3077+ nvme_show_error ("persistent event log: %s" , nvme_strerror (err ));
3078+ return err ;
3079+ } else if (err ) {
3080+ nvme_show_status (err );
3081+ return err ;
3082+ }
3083+ pevent_collected = pevent_log_info ;
3084+ if (pevent_collected -> gen_number != pevent -> gen_number ) {
3085+ printf ("Collected Persistent Event Log may be invalid,\n"
3086+ "Re-read the log is required\n" );
3087+ return - EINVAL ;
3088+ }
3089+
3090+ ocp_show_persistent_event_log (pevent_log_info , cfg .action ,
3091+ cfg .log_len , nvme_transport_handle_get_name (hdl ), flags );
3092+ } else if (err > 0 ) {
3093+ nvme_show_status (err );
3094+ } else {
3095+ nvme_show_error ("persistent event log: %s" , nvme_strerror (err ));
3096+ }
3097+
3098+ return err ;
3099+ }
0 commit comments