linux/drivers/platform/x86/intel/telemetry/core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Intel SoC Core Telemetry Driver
   4 * Copyright (C) 2015, Intel Corporation.
   5 * All Rights Reserved.
   6 *
   7 * Telemetry Framework provides platform related PM and performance statistics.
   8 * This file provides the core telemetry API implementation.
   9 */
  10#include <linux/device.h>
  11#include <linux/module.h>
  12
  13#include <asm/intel_telemetry.h>
  14
  15#define DRIVER_NAME "intel_telemetry_core"
  16
  17struct telemetry_core_config {
  18        struct telemetry_plt_config *plt_config;
  19        const struct telemetry_core_ops *telem_ops;
  20};
  21
  22static struct telemetry_core_config telm_core_conf;
  23
  24static int telemetry_def_update_events(struct telemetry_evtconfig pss_evtconfig,
  25                                      struct telemetry_evtconfig ioss_evtconfig)
  26{
  27        return 0;
  28}
  29
  30static int telemetry_def_set_sampling_period(u8 pss_period, u8 ioss_period)
  31{
  32        return 0;
  33}
  34
  35static int telemetry_def_get_sampling_period(u8 *pss_min_period,
  36                                             u8 *pss_max_period,
  37                                             u8 *ioss_min_period,
  38                                             u8 *ioss_max_period)
  39{
  40        return 0;
  41}
  42
  43static int telemetry_def_get_eventconfig(
  44                        struct telemetry_evtconfig *pss_evtconfig,
  45                        struct telemetry_evtconfig *ioss_evtconfig,
  46                        int pss_len, int ioss_len)
  47{
  48        return 0;
  49}
  50
  51static int telemetry_def_get_trace_verbosity(enum telemetry_unit telem_unit,
  52                                             u32 *verbosity)
  53{
  54        return 0;
  55}
  56
  57
  58static int telemetry_def_set_trace_verbosity(enum telemetry_unit telem_unit,
  59                                             u32 verbosity)
  60{
  61        return 0;
  62}
  63
  64static int telemetry_def_raw_read_eventlog(enum telemetry_unit telem_unit,
  65                                           struct telemetry_evtlog *evtlog,
  66                                           int len, int log_all_evts)
  67{
  68        return 0;
  69}
  70
  71static int telemetry_def_read_eventlog(enum telemetry_unit telem_unit,
  72                                       struct telemetry_evtlog *evtlog,
  73                                       int len, int log_all_evts)
  74{
  75        return 0;
  76}
  77
  78static int telemetry_def_add_events(u8 num_pss_evts, u8 num_ioss_evts,
  79                                    u32 *pss_evtmap, u32 *ioss_evtmap)
  80{
  81        return 0;
  82}
  83
  84static int telemetry_def_reset_events(void)
  85{
  86        return 0;
  87}
  88
  89static const struct telemetry_core_ops telm_defpltops = {
  90        .set_sampling_period = telemetry_def_set_sampling_period,
  91        .get_sampling_period = telemetry_def_get_sampling_period,
  92        .get_trace_verbosity = telemetry_def_get_trace_verbosity,
  93        .set_trace_verbosity = telemetry_def_set_trace_verbosity,
  94        .raw_read_eventlog = telemetry_def_raw_read_eventlog,
  95        .get_eventconfig = telemetry_def_get_eventconfig,
  96        .read_eventlog = telemetry_def_read_eventlog,
  97        .update_events = telemetry_def_update_events,
  98        .reset_events = telemetry_def_reset_events,
  99        .add_events = telemetry_def_add_events,
 100};
 101
 102/**
 103 * telemetry_update_events() - Update telemetry Configuration
 104 * @pss_evtconfig: PSS related config. No change if num_evts = 0.
 105 * @pss_evtconfig: IOSS related config. No change if num_evts = 0.
 106 *
 107 * This API updates the IOSS & PSS Telemetry configuration. Old config
 108 * is overwritten. Call telemetry_reset_events when logging is over
 109 * All sample period values should be in the form of:
 110 * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
 111 *
 112 * Return: 0 success, < 0 for failure
 113 */
 114int telemetry_update_events(struct telemetry_evtconfig pss_evtconfig,
 115                            struct telemetry_evtconfig ioss_evtconfig)
 116{
 117        return telm_core_conf.telem_ops->update_events(pss_evtconfig,
 118                                                       ioss_evtconfig);
 119}
 120EXPORT_SYMBOL_GPL(telemetry_update_events);
 121
 122
 123/**
 124 * telemetry_set_sampling_period() - Sets the IOSS & PSS sampling period
 125 * @pss_period:  placeholder for PSS Period to be set.
 126 *               Set to 0 if not required to be updated
 127 * @ioss_period: placeholder for IOSS Period to be set
 128 *               Set to 0 if not required to be updated
 129 *
 130 * All values should be in the form of:
 131 * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
 132 *
 133 * Return: 0 success, < 0 for failure
 134 */
 135int telemetry_set_sampling_period(u8 pss_period, u8 ioss_period)
 136{
 137        return telm_core_conf.telem_ops->set_sampling_period(pss_period,
 138                                                             ioss_period);
 139}
 140EXPORT_SYMBOL_GPL(telemetry_set_sampling_period);
 141
 142/**
 143 * telemetry_get_sampling_period() - Get IOSS & PSS min & max sampling period
 144 * @pss_min_period:  placeholder for PSS Min Period supported
 145 * @pss_max_period:  placeholder for PSS Max Period supported
 146 * @ioss_min_period: placeholder for IOSS Min Period supported
 147 * @ioss_max_period: placeholder for IOSS Max Period supported
 148 *
 149 * All values should be in the form of:
 150 * bits[6:3] -> value; bits [0:2]-> Exponent; Period = (Value *16^Exponent)
 151 *
 152 * Return: 0 success, < 0 for failure
 153 */
 154int telemetry_get_sampling_period(u8 *pss_min_period, u8 *pss_max_period,
 155                                  u8 *ioss_min_period, u8 *ioss_max_period)
 156{
 157        return telm_core_conf.telem_ops->get_sampling_period(pss_min_period,
 158                                                             pss_max_period,
 159                                                             ioss_min_period,
 160                                                             ioss_max_period);
 161}
 162EXPORT_SYMBOL_GPL(telemetry_get_sampling_period);
 163
 164
 165/**
 166 * telemetry_reset_events() - Restore the IOSS & PSS configuration to default
 167 *
 168 * Return: 0 success, < 0 for failure
 169 */
 170int telemetry_reset_events(void)
 171{
 172        return telm_core_conf.telem_ops->reset_events();
 173}
 174EXPORT_SYMBOL_GPL(telemetry_reset_events);
 175
 176/**
 177 * telemetry_get_eventconfig() - Returns the pss and ioss events enabled
 178 * @pss_evtconfig: Pointer to PSS related configuration.
 179 * @pss_evtconfig: Pointer to IOSS related configuration.
 180 * @pss_len:       Number of u32 elements allocated for pss_evtconfig array
 181 * @ioss_len:      Number of u32 elements allocated for ioss_evtconfig array
 182 *
 183 * Return: 0 success, < 0 for failure
 184 */
 185int telemetry_get_eventconfig(struct telemetry_evtconfig *pss_evtconfig,
 186                              struct telemetry_evtconfig *ioss_evtconfig,
 187                              int pss_len, int ioss_len)
 188{
 189        return telm_core_conf.telem_ops->get_eventconfig(pss_evtconfig,
 190                                                         ioss_evtconfig,
 191                                                         pss_len, ioss_len);
 192}
 193EXPORT_SYMBOL_GPL(telemetry_get_eventconfig);
 194
 195/**
 196 * telemetry_add_events() - Add IOSS & PSS configuration to existing settings.
 197 * @num_pss_evts:  Number of PSS Events (<29) in pss_evtmap. Can be 0.
 198 * @num_ioss_evts: Number of IOSS Events (<29) in ioss_evtmap. Can be 0.
 199 * @pss_evtmap:    Array of PSS Event-IDs to Enable
 200 * @ioss_evtmap:   Array of PSS Event-IDs to Enable
 201 *
 202 * Events are appended to Old Configuration. In case of total events > 28, it
 203 * returns error. Call telemetry_reset_events to reset after eventlog done
 204 *
 205 * Return: 0 success, < 0 for failure
 206 */
 207int telemetry_add_events(u8 num_pss_evts, u8 num_ioss_evts,
 208                         u32 *pss_evtmap, u32 *ioss_evtmap)
 209{
 210        return telm_core_conf.telem_ops->add_events(num_pss_evts,
 211                                                    num_ioss_evts, pss_evtmap,
 212                                                    ioss_evtmap);
 213}
 214EXPORT_SYMBOL_GPL(telemetry_add_events);
 215
 216/**
 217 * telemetry_read_events() - Fetches samples as specified by evtlog.telem_evt_id
 218 * @telem_unit: Specify whether IOSS or PSS Read
 219 * @evtlog:     Array of telemetry_evtlog structs to fill data
 220 *              evtlog.telem_evt_id specifies the ids to read
 221 * @len:        Length of array of evtlog
 222 *
 223 * Return: number of eventlogs read for success, < 0 for failure
 224 */
 225int telemetry_read_events(enum telemetry_unit telem_unit,
 226                          struct telemetry_evtlog *evtlog, int len)
 227{
 228        return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
 229                                                       len, 0);
 230}
 231EXPORT_SYMBOL_GPL(telemetry_read_events);
 232
 233/**
 234 * telemetry_raw_read_events() - Fetch samples specified by evtlog.telem_evt_id
 235 * @telem_unit: Specify whether IOSS or PSS Read
 236 * @evtlog:     Array of telemetry_evtlog structs to fill data
 237 *              evtlog.telem_evt_id specifies the ids to read
 238 * @len:        Length of array of evtlog
 239 *
 240 * The caller must take care of locking in this case.
 241 *
 242 * Return: number of eventlogs read for success, < 0 for failure
 243 */
 244int telemetry_raw_read_events(enum telemetry_unit telem_unit,
 245                              struct telemetry_evtlog *evtlog, int len)
 246{
 247        return telm_core_conf.telem_ops->raw_read_eventlog(telem_unit, evtlog,
 248                                                           len, 0);
 249}
 250EXPORT_SYMBOL_GPL(telemetry_raw_read_events);
 251
 252/**
 253 * telemetry_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
 254 * @telem_unit: Specify whether IOSS or PSS Read
 255 * @evtlog:     Array of telemetry_evtlog structs to fill data
 256 * @len:        Length of array of evtlog
 257 *
 258 * Return: number of eventlogs read for success, < 0 for failure
 259 */
 260int telemetry_read_eventlog(enum telemetry_unit telem_unit,
 261                            struct telemetry_evtlog *evtlog, int len)
 262{
 263        return telm_core_conf.telem_ops->read_eventlog(telem_unit, evtlog,
 264                                                       len, 1);
 265}
 266EXPORT_SYMBOL_GPL(telemetry_read_eventlog);
 267
 268/**
 269 * telemetry_raw_read_eventlog() - Fetch the Telemetry log from PSS or IOSS
 270 * @telem_unit: Specify whether IOSS or PSS Read
 271 * @evtlog:     Array of telemetry_evtlog structs to fill data
 272 * @len:        Length of array of evtlog
 273 *
 274 * The caller must take care of locking in this case.
 275 *
 276 * Return: number of eventlogs read for success, < 0 for failure
 277 */
 278int telemetry_raw_read_eventlog(enum telemetry_unit telem_unit,
 279                                struct telemetry_evtlog *evtlog, int len)
 280{
 281        return telm_core_conf.telem_ops->raw_read_eventlog(telem_unit, evtlog,
 282                                                           len, 1);
 283}
 284EXPORT_SYMBOL_GPL(telemetry_raw_read_eventlog);
 285
 286
 287/**
 288 * telemetry_get_trace_verbosity() - Get the IOSS & PSS Trace verbosity
 289 * @telem_unit: Specify whether IOSS or PSS Read
 290 * @verbosity:  Pointer to return Verbosity
 291 *
 292 * Return: 0 success, < 0 for failure
 293 */
 294int telemetry_get_trace_verbosity(enum telemetry_unit telem_unit,
 295                                  u32 *verbosity)
 296{
 297        return telm_core_conf.telem_ops->get_trace_verbosity(telem_unit,
 298                                                             verbosity);
 299}
 300EXPORT_SYMBOL_GPL(telemetry_get_trace_verbosity);
 301
 302
 303/**
 304 * telemetry_set_trace_verbosity() - Update the IOSS & PSS Trace verbosity
 305 * @telem_unit: Specify whether IOSS or PSS Read
 306 * @verbosity:  Verbosity to set
 307 *
 308 * Return: 0 success, < 0 for failure
 309 */
 310int telemetry_set_trace_verbosity(enum telemetry_unit telem_unit, u32 verbosity)
 311{
 312        return telm_core_conf.telem_ops->set_trace_verbosity(telem_unit,
 313                                                             verbosity);
 314}
 315EXPORT_SYMBOL_GPL(telemetry_set_trace_verbosity);
 316
 317/**
 318 * telemetry_set_pltdata() - Set the platform specific Data
 319 * @ops:        Pointer to ops structure
 320 * @pltconfig:  Platform config data
 321 *
 322 * Usage by other than telemetry pltdrv module is invalid
 323 *
 324 * Return: 0 success, < 0 for failure
 325 */
 326int telemetry_set_pltdata(const struct telemetry_core_ops *ops,
 327                          struct telemetry_plt_config *pltconfig)
 328{
 329        if (ops)
 330                telm_core_conf.telem_ops = ops;
 331
 332        if (pltconfig)
 333                telm_core_conf.plt_config = pltconfig;
 334
 335        return 0;
 336}
 337EXPORT_SYMBOL_GPL(telemetry_set_pltdata);
 338
 339/**
 340 * telemetry_clear_pltdata() - Clear the platform specific Data
 341 *
 342 * Usage by other than telemetry pltdrv module is invalid
 343 *
 344 * Return: 0 success, < 0 for failure
 345 */
 346int telemetry_clear_pltdata(void)
 347{
 348        telm_core_conf.telem_ops = &telm_defpltops;
 349        telm_core_conf.plt_config = NULL;
 350
 351        return 0;
 352}
 353EXPORT_SYMBOL_GPL(telemetry_clear_pltdata);
 354
 355/**
 356 * telemetry_get_pltdata() - Return telemetry platform config
 357 *
 358 * May be used by other telemetry modules to get platform specific
 359 * configuration.
 360 */
 361struct telemetry_plt_config *telemetry_get_pltdata(void)
 362{
 363        return telm_core_conf.plt_config;
 364}
 365EXPORT_SYMBOL_GPL(telemetry_get_pltdata);
 366
 367static inline int telemetry_get_pssevtname(enum telemetry_unit telem_unit,
 368                                           const char **name, int len)
 369{
 370        struct telemetry_unit_config psscfg;
 371        int i;
 372
 373        if (!telm_core_conf.plt_config)
 374                return -EINVAL;
 375
 376        psscfg = telm_core_conf.plt_config->pss_config;
 377
 378        if (len > psscfg.ssram_evts_used)
 379                len = psscfg.ssram_evts_used;
 380
 381        for (i = 0; i < len; i++)
 382                name[i] = psscfg.telem_evts[i].name;
 383
 384        return 0;
 385}
 386
 387static inline int telemetry_get_iossevtname(enum telemetry_unit telem_unit,
 388                                            const char **name, int len)
 389{
 390        struct telemetry_unit_config iosscfg;
 391        int i;
 392
 393        if (!(telm_core_conf.plt_config))
 394                return -EINVAL;
 395
 396        iosscfg = telm_core_conf.plt_config->ioss_config;
 397
 398        if (len > iosscfg.ssram_evts_used)
 399                len = iosscfg.ssram_evts_used;
 400
 401        for (i = 0; i < len; i++)
 402                name[i] = iosscfg.telem_evts[i].name;
 403
 404        return 0;
 405
 406}
 407
 408/**
 409 * telemetry_get_evtname() - Checkif platform config is valid
 410 * @telem_unit: Telemetry Unit to check
 411 * @name:       Array of character pointers to contain name
 412 * @len:        length of array name provided by user
 413 *
 414 * Usage by other than telemetry debugfs module is invalid
 415 *
 416 * Return: 0 success, < 0 for failure
 417 */
 418int telemetry_get_evtname(enum telemetry_unit telem_unit,
 419                          const char **name, int len)
 420{
 421        int ret = -EINVAL;
 422
 423        if (telem_unit == TELEM_PSS)
 424                ret = telemetry_get_pssevtname(telem_unit, name, len);
 425
 426        else if (telem_unit == TELEM_IOSS)
 427                ret = telemetry_get_iossevtname(telem_unit, name, len);
 428
 429        return ret;
 430}
 431EXPORT_SYMBOL_GPL(telemetry_get_evtname);
 432
 433static int __init telemetry_module_init(void)
 434{
 435        pr_info(pr_fmt(DRIVER_NAME) " Init\n");
 436
 437        telm_core_conf.telem_ops = &telm_defpltops;
 438        return 0;
 439}
 440
 441static void __exit telemetry_module_exit(void)
 442{
 443}
 444
 445module_init(telemetry_module_init);
 446module_exit(telemetry_module_exit);
 447
 448MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
 449MODULE_DESCRIPTION("Intel SoC Telemetry Interface");
 450MODULE_LICENSE("GPL v2");
 451