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