Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Intel SoC Core Telemetry Driver
0004  * Copyright (C) 2015, Intel Corporation.
0005  * All Rights Reserved.
0006  *
0007  * Telemetry Framework provides platform related PM and performance statistics.
0008  * This file provides the core telemetry API implementation.
0009  */
0010 #include <linux/device.h>
0011 #include <linux/module.h>
0012 
0013 #include <asm/intel_telemetry.h>
0014 
0015 #define DRIVER_NAME "intel_telemetry_core"
0016 
0017 struct telemetry_core_config {
0018     struct telemetry_plt_config *plt_config;
0019     const struct telemetry_core_ops *telem_ops;
0020 };
0021 
0022 static struct telemetry_core_config telm_core_conf;
0023 
0024 static int telemetry_def_update_events(struct telemetry_evtconfig pss_evtconfig,
0025                       struct telemetry_evtconfig ioss_evtconfig)
0026 {
0027     return 0;
0028 }
0029 
0030 static int telemetry_def_set_sampling_period(u8 pss_period, u8 ioss_period)
0031 {
0032     return 0;
0033 }
0034 
0035 static int telemetry_def_get_sampling_period(u8 *pss_min_period,
0036                          u8 *pss_max_period,
0037                          u8 *ioss_min_period,
0038                          u8 *ioss_max_period)
0039 {
0040     return 0;
0041 }
0042 
0043 static int telemetry_def_get_eventconfig(
0044             struct telemetry_evtconfig *pss_evtconfig,
0045             struct telemetry_evtconfig *ioss_evtconfig,
0046             int pss_len, int ioss_len)
0047 {
0048     return 0;
0049 }
0050 
0051 static int telemetry_def_get_trace_verbosity(enum telemetry_unit telem_unit,
0052                          u32 *verbosity)
0053 {
0054     return 0;
0055 }
0056 
0057 
0058 static int telemetry_def_set_trace_verbosity(enum telemetry_unit telem_unit,
0059                          u32 verbosity)
0060 {
0061     return 0;
0062 }
0063 
0064 static int telemetry_def_raw_read_eventlog(enum telemetry_unit telem_unit,
0065                        struct telemetry_evtlog *evtlog,
0066                        int len, int log_all_evts)
0067 {
0068     return 0;
0069 }
0070 
0071 static int telemetry_def_read_eventlog(enum telemetry_unit telem_unit,
0072                        struct telemetry_evtlog *evtlog,
0073                        int len, int log_all_evts)
0074 {
0075     return 0;
0076 }
0077 
0078 static int telemetry_def_add_events(u8 num_pss_evts, u8 num_ioss_evts,
0079                     u32 *pss_evtmap, u32 *ioss_evtmap)
0080 {
0081     return 0;
0082 }
0083 
0084 static int telemetry_def_reset_events(void)
0085 {
0086     return 0;
0087 }
0088 
0089 static const struct telemetry_core_ops telm_defpltops = {
0090     .set_sampling_period = telemetry_def_set_sampling_period,
0091     .get_sampling_period = telemetry_def_get_sampling_period,
0092     .get_trace_verbosity = telemetry_def_get_trace_verbosity,
0093     .set_trace_verbosity = telemetry_def_set_trace_verbosity,
0094     .raw_read_eventlog = telemetry_def_raw_read_eventlog,
0095     .get_eventconfig = telemetry_def_get_eventconfig,
0096     .read_eventlog = telemetry_def_read_eventlog,
0097     .update_events = telemetry_def_update_events,
0098     .reset_events = telemetry_def_reset_events,
0099     .add_events = telemetry_def_add_events,
0100 };
0101 
0102 /**
0103  * telemetry_update_events() - Update telemetry Configuration
0104  * @pss_evtconfig: PSS related config. No change if num_evts = 0.
0105  * @pss_evtconfig: IOSS related config. No change if num_evts = 0.
0106  *
0107  * This API updates the IOSS & PSS Telemetry configuration. Old config
0108  * is overwritten. Call telemetry_reset_events when logging is over
0109  * All sample period values should be in the form of:
0110  * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
0111  *
0112  * Return: 0 success, < 0 for failure
0113  */
0114 int telemetry_update_events(struct telemetry_evtconfig pss_evtconfig,
0115                 struct telemetry_evtconfig ioss_evtconfig)
0116 {
0117     return telm_core_conf.telem_ops->update_events(pss_evtconfig,
0118                                ioss_evtconfig);
0119 }
0120 EXPORT_SYMBOL_GPL(telemetry_update_events);
0121 
0122 
0123 /**
0124  * telemetry_set_sampling_period() - Sets the IOSS & PSS sampling period
0125  * @pss_period:  placeholder for PSS Period to be set.
0126  *       Set to 0 if not required to be updated
0127  * @ioss_period: placeholder for IOSS Period to be set
0128  *       Set to 0 if not required to be updated
0129  *
0130  * All values should be in the form of:
0131  * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
0132  *
0133  * Return: 0 success, < 0 for failure
0134  */
0135 int telemetry_set_sampling_period(u8 pss_period, u8 ioss_period)
0136 {
0137     return telm_core_conf.telem_ops->set_sampling_period(pss_period,
0138                                  ioss_period);
0139 }
0140 EXPORT_SYMBOL_GPL(telemetry_set_sampling_period);
0141 
0142 /**
0143  * telemetry_get_sampling_period() - Get IOSS & PSS min & max sampling period
0144  * @pss_min_period:  placeholder for PSS Min Period supported
0145  * @pss_max_period:  placeholder for PSS Max Period supported
0146  * @ioss_min_period: placeholder for IOSS Min Period supported
0147  * @ioss_max_period: placeholder for IOSS Max Period supported
0148  *
0149  * All values should be in the form of:
0150  * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
0151  *
0152  * Return: 0 success, < 0 for failure
0153  */
0154 int telemetry_get_sampling_period(u8 *pss_min_period, u8 *pss_max_period,
0155                   u8 *ioss_min_period, u8 *ioss_max_period)
0156 {
0157     return telm_core_conf.telem_ops->get_sampling_period(pss_min_period,
0158                                  pss_max_period,
0159                                  ioss_min_period,
0160                                  ioss_max_period);
0161 }
0162 EXPORT_SYMBOL_GPL(telemetry_get_sampling_period);
0163 
0164 
0165 /**
0166  * telemetry_reset_events() - Restore the IOSS & PSS configuration to default
0167  *
0168  * Return: 0 success, < 0 for failure
0169  */
0170 int telemetry_reset_events(void)
0171 {
0172     return telm_core_conf.telem_ops->reset_events();
0173 }
0174 EXPORT_SYMBOL_GPL(telemetry_reset_events);
0175 
0176 /**
0177  * telemetry_get_eventconfig() - Returns the pss and ioss events enabled
0178  * @pss_evtconfig: Pointer to PSS related configuration.
0179  * @pss_evtconfig: Pointer to IOSS related configuration.
0180  * @pss_len:       Number of u32 elements allocated for pss_evtconfig array
0181  * @ioss_len:      Number of u32 elements allocated for ioss_evtconfig array
0182  *
0183  * Return: 0 success, < 0 for failure
0184  */
0185 int telemetry_get_eventconfig(struct telemetry_evtconfig *pss_evtconfig,
0186                   struct telemetry_evtconfig *ioss_evtconfig,
0187                   int pss_len, int ioss_len)
0188 {
0189     return telm_core_conf.telem_ops->get_eventconfig(pss_evtconfig,
0190                              ioss_evtconfig,
0191                              pss_len, ioss_len);
0192 }
0193 EXPORT_SYMBOL_GPL(telemetry_get_eventconfig);
0194 
0195 /**
0196  * telemetry_add_events() - Add IOSS & PSS configuration to existing settings.
0197  * @num_pss_evts:  Number of PSS Events (<29) in pss_evtmap. Can be 0.
0198  * @num_ioss_evts: Number of IOSS Events (<29) in ioss_evtmap. Can be 0.
0199  * @pss_evtmap:    Array of PSS Event-IDs to Enable
0200  * @ioss_evtmap:   Array of PSS Event-IDs to Enable
0201  *
0202  * Events are appended to Old Configuration. In case of total events > 28, it
0203  * returns error. Call telemetry_reset_events to reset after eventlog done
0204  *
0205  * Return: 0 success, < 0 for failure
0206  */
0207 int telemetry_add_events(u8 num_pss_evts, u8 num_ioss_evts,
0208              u32 *pss_evtmap, u32 *ioss_evtmap)
0209 {
0210     return telm_core_conf.telem_ops->add_events(num_pss_evts,
0211                             num_ioss_evts, pss_evtmap,
0212                             ioss_evtmap);
0213 }
0214 EXPORT_SYMBOL_GPL(telemetry_add_events);
0215 
0216 /**
0217  * telemetry_read_events() - Fetches samples as specified by evtlog.telem_evt_id
0218  * @telem_unit: Specify whether IOSS or PSS Read
0219  * @evtlog:     Array of telemetry_evtlog structs to fill data
0220  *      evtlog.telem_evt_id specifies the ids to read
0221  * @len:    Length of array of evtlog
0222  *
0223  * Return: number of eventlogs read for success, < 0 for failure
0224  */
0225 int telemetry_read_events(enum telemetry_unit telem_unit,
0226               struct telemetry_evtlog *evtlog, int len)
0227 {
0228     return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
0229                                len, 0);
0230 }
0231 EXPORT_SYMBOL_GPL(telemetry_read_events);
0232 
0233 /**
0234  * telemetry_raw_read_events() - Fetch samples specified by evtlog.telem_evt_id
0235  * @telem_unit: Specify whether IOSS or PSS Read
0236  * @evtlog: Array of telemetry_evtlog structs to fill data
0237  *      evtlog.telem_evt_id specifies the ids to read
0238  * @len:    Length of array of evtlog
0239  *
0240  * The caller must take care of locking in this case.
0241  *
0242  * Return: number of eventlogs read for success, < 0 for failure
0243  */
0244 int telemetry_raw_read_events(enum telemetry_unit telem_unit,
0245                   struct telemetry_evtlog *evtlog, int len)
0246 {
0247     return telm_core_conf.telem_ops->raw_read_eventlog(telem_unit, evtlog,
0248                                len, 0);
0249 }
0250 EXPORT_SYMBOL_GPL(telemetry_raw_read_events);
0251 
0252 /**
0253  * telemetry_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
0254  * @telem_unit: Specify whether IOSS or PSS Read
0255  * @evtlog: Array of telemetry_evtlog structs to fill data
0256  * @len:    Length of array of evtlog
0257  *
0258  * Return: number of eventlogs read for success, < 0 for failure
0259  */
0260 int telemetry_read_eventlog(enum telemetry_unit telem_unit,
0261                 struct telemetry_evtlog *evtlog, int len)
0262 {
0263     return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
0264                                len, 1);
0265 }
0266 EXPORT_SYMBOL_GPL(telemetry_read_eventlog);
0267 
0268 /**
0269  * telemetry_raw_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
0270  * @telem_unit: Specify whether IOSS or PSS Read
0271  * @evtlog: Array of telemetry_evtlog structs to fill data
0272  * @len:    Length of array of evtlog
0273  *
0274  * The caller must take care of locking in this case.
0275  *
0276  * Return: number of eventlogs read for success, < 0 for failure
0277  */
0278 int telemetry_raw_read_eventlog(enum telemetry_unit telem_unit,
0279                 struct telemetry_evtlog *evtlog, int len)
0280 {
0281     return telm_core_conf.telem_ops->raw_read_eventlog(telem_unit, evtlog,
0282                                len, 1);
0283 }
0284 EXPORT_SYMBOL_GPL(telemetry_raw_read_eventlog);
0285 
0286 
0287 /**
0288  * telemetry_get_trace_verbosity() - Get the IOSS & PSS Trace verbosity
0289  * @telem_unit: Specify whether IOSS or PSS Read
0290  * @verbosity:  Pointer to return Verbosity
0291  *
0292  * Return: 0 success, < 0 for failure
0293  */
0294 int telemetry_get_trace_verbosity(enum telemetry_unit telem_unit,
0295                   u32 *verbosity)
0296 {
0297     return telm_core_conf.telem_ops->get_trace_verbosity(telem_unit,
0298                                  verbosity);
0299 }
0300 EXPORT_SYMBOL_GPL(telemetry_get_trace_verbosity);
0301 
0302 
0303 /**
0304  * telemetry_set_trace_verbosity() - Update the IOSS & PSS Trace verbosity
0305  * @telem_unit: Specify whether IOSS or PSS Read
0306  * @verbosity:  Verbosity to set
0307  *
0308  * Return: 0 success, < 0 for failure
0309  */
0310 int telemetry_set_trace_verbosity(enum telemetry_unit telem_unit, u32 verbosity)
0311 {
0312     return telm_core_conf.telem_ops->set_trace_verbosity(telem_unit,
0313                                  verbosity);
0314 }
0315 EXPORT_SYMBOL_GPL(telemetry_set_trace_verbosity);
0316 
0317 /**
0318  * telemetry_set_pltdata() - Set the platform specific Data
0319  * @ops:    Pointer to ops structure
0320  * @pltconfig:  Platform config data
0321  *
0322  * Usage by other than telemetry pltdrv module is invalid
0323  *
0324  * Return: 0 success, < 0 for failure
0325  */
0326 int telemetry_set_pltdata(const struct telemetry_core_ops *ops,
0327               struct telemetry_plt_config *pltconfig)
0328 {
0329     if (ops)
0330         telm_core_conf.telem_ops = ops;
0331 
0332     if (pltconfig)
0333         telm_core_conf.plt_config = pltconfig;
0334 
0335     return 0;
0336 }
0337 EXPORT_SYMBOL_GPL(telemetry_set_pltdata);
0338 
0339 /**
0340  * telemetry_clear_pltdata() - Clear the platform specific Data
0341  *
0342  * Usage by other than telemetry pltdrv module is invalid
0343  *
0344  * Return: 0 success, < 0 for failure
0345  */
0346 int telemetry_clear_pltdata(void)
0347 {
0348     telm_core_conf.telem_ops = &telm_defpltops;
0349     telm_core_conf.plt_config = NULL;
0350 
0351     return 0;
0352 }
0353 EXPORT_SYMBOL_GPL(telemetry_clear_pltdata);
0354 
0355 /**
0356  * telemetry_get_pltdata() - Return telemetry platform config
0357  *
0358  * May be used by other telemetry modules to get platform specific
0359  * configuration.
0360  */
0361 struct telemetry_plt_config *telemetry_get_pltdata(void)
0362 {
0363     return telm_core_conf.plt_config;
0364 }
0365 EXPORT_SYMBOL_GPL(telemetry_get_pltdata);
0366 
0367 static inline int telemetry_get_pssevtname(enum telemetry_unit telem_unit,
0368                        const char **name, int len)
0369 {
0370     struct telemetry_unit_config psscfg;
0371     int i;
0372 
0373     if (!telm_core_conf.plt_config)
0374         return -EINVAL;
0375 
0376     psscfg = telm_core_conf.plt_config->pss_config;
0377 
0378     if (len > psscfg.ssram_evts_used)
0379         len = psscfg.ssram_evts_used;
0380 
0381     for (i = 0; i < len; i++)
0382         name[i] = psscfg.telem_evts[i].name;
0383 
0384     return 0;
0385 }
0386 
0387 static inline int telemetry_get_iossevtname(enum telemetry_unit telem_unit,
0388                         const char **name, int len)
0389 {
0390     struct telemetry_unit_config iosscfg;
0391     int i;
0392 
0393     if (!(telm_core_conf.plt_config))
0394         return -EINVAL;
0395 
0396     iosscfg = telm_core_conf.plt_config->ioss_config;
0397 
0398     if (len > iosscfg.ssram_evts_used)
0399         len = iosscfg.ssram_evts_used;
0400 
0401     for (i = 0; i < len; i++)
0402         name[i] = iosscfg.telem_evts[i].name;
0403 
0404     return 0;
0405 
0406 }
0407 
0408 /**
0409  * telemetry_get_evtname() - Checkif platform config is valid
0410  * @telem_unit: Telemetry Unit to check
0411  * @name:   Array of character pointers to contain name
0412  * @len:    length of array name provided by user
0413  *
0414  * Usage by other than telemetry debugfs module is invalid
0415  *
0416  * Return: 0 success, < 0 for failure
0417  */
0418 int telemetry_get_evtname(enum telemetry_unit telem_unit,
0419               const char **name, int len)
0420 {
0421     int ret = -EINVAL;
0422 
0423     if (telem_unit == TELEM_PSS)
0424         ret = telemetry_get_pssevtname(telem_unit, name, len);
0425 
0426     else if (telem_unit == TELEM_IOSS)
0427         ret = telemetry_get_iossevtname(telem_unit, name, len);
0428 
0429     return ret;
0430 }
0431 EXPORT_SYMBOL_GPL(telemetry_get_evtname);
0432 
0433 static int __init telemetry_module_init(void)
0434 {
0435     pr_info(pr_fmt(DRIVER_NAME) " Init\n");
0436 
0437     telm_core_conf.telem_ops = &telm_defpltops;
0438     return 0;
0439 }
0440 
0441 static void __exit telemetry_module_exit(void)
0442 {
0443 }
0444 
0445 module_init(telemetry_module_init);
0446 module_exit(telemetry_module_exit);
0447 
0448 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
0449 MODULE_DESCRIPTION("Intel SoC Telemetry Interface");
0450 MODULE_LICENSE("GPL v2");