linux/tools/power/x86/intel-speed-select/isst-config.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Intel Speed Select -- Enumerate and control features
   4 * Copyright (c) 2019 Intel Corporation.
   5 */
   6
   7#include <linux/isst_if.h>
   8
   9#include "isst.h"
  10
  11struct process_cmd_struct {
  12        char *feature;
  13        char *command;
  14        void (*process_fn)(int arg);
  15        int arg;
  16};
  17
  18static const char *version_str = "v1.5";
  19static const int supported_api_ver = 1;
  20static struct isst_if_platform_info isst_platform_info;
  21static char *progname;
  22static int debug_flag;
  23static FILE *outf;
  24
  25static int cpu_model;
  26static int cpu_stepping;
  27
  28#define MAX_CPUS_IN_ONE_REQ 256
  29static short max_target_cpus;
  30static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
  31
  32static int topo_max_cpus;
  33static size_t present_cpumask_size;
  34static cpu_set_t *present_cpumask;
  35static size_t target_cpumask_size;
  36static cpu_set_t *target_cpumask;
  37static int tdp_level = 0xFF;
  38static int fact_bucket = 0xFF;
  39static int fact_avx = 0xFF;
  40static unsigned long long fact_trl;
  41static int out_format_json;
  42static int cmd_help;
  43static int force_online_offline;
  44static int auto_mode;
  45static int fact_enable_fail;
  46
  47static int mbox_delay;
  48static int mbox_retries = 3;
  49
  50/* clos related */
  51static int current_clos = -1;
  52static int clos_epp = -1;
  53static int clos_prop_prio = -1;
  54static int clos_min = -1;
  55static int clos_max = -1;
  56static int clos_desired = -1;
  57static int clos_priority_type;
  58
  59struct _cpu_map {
  60        unsigned short core_id;
  61        unsigned short pkg_id;
  62        unsigned short die_id;
  63        unsigned short punit_cpu;
  64        unsigned short punit_cpu_core;
  65};
  66struct _cpu_map *cpu_map;
  67
  68struct cpu_topology {
  69        short cpu;
  70        short core_id;
  71        short pkg_id;
  72        short die_id;
  73};
  74
  75FILE *get_output_file(void)
  76{
  77        return outf;
  78}
  79
  80void debug_printf(const char *format, ...)
  81{
  82        va_list args;
  83
  84        va_start(args, format);
  85
  86        if (debug_flag)
  87                vprintf(format, args);
  88
  89        va_end(args);
  90}
  91
  92
  93int is_clx_n_platform(void)
  94{
  95        if (cpu_model == 0x55)
  96                if (cpu_stepping == 0x6 || cpu_stepping == 0x7)
  97                        return 1;
  98        return 0;
  99}
 100
 101int is_skx_based_platform(void)
 102{
 103        if (cpu_model == 0x55)
 104                return 1;
 105
 106        return 0;
 107}
 108
 109static int update_cpu_model(void)
 110{
 111        unsigned int ebx, ecx, edx;
 112        unsigned int fms, family;
 113
 114        __cpuid(1, fms, ebx, ecx, edx);
 115        family = (fms >> 8) & 0xf;
 116        cpu_model = (fms >> 4) & 0xf;
 117        if (family == 6 || family == 0xf)
 118                cpu_model += ((fms >> 16) & 0xf) << 4;
 119
 120        cpu_stepping = fms & 0xf;
 121        /* only three CascadeLake-N models are supported */
 122        if (is_clx_n_platform()) {
 123                FILE *fp;
 124                size_t n = 0;
 125                char *line = NULL;
 126                int ret = 1;
 127
 128                fp = fopen("/proc/cpuinfo", "r");
 129                if (!fp)
 130                        err(-1, "cannot open /proc/cpuinfo\n");
 131
 132                while (getline(&line, &n, fp) > 0) {
 133                        if (strstr(line, "model name")) {
 134                                if (strstr(line, "6252N") ||
 135                                    strstr(line, "6230N") ||
 136                                    strstr(line, "5218N"))
 137                                        ret = 0;
 138                                break;
 139                        }
 140                }
 141                free(line);
 142                fclose(fp);
 143                return ret;
 144        }
 145        return 0;
 146}
 147
 148/* Open a file, and exit on failure */
 149static FILE *fopen_or_exit(const char *path, const char *mode)
 150{
 151        FILE *filep = fopen(path, mode);
 152
 153        if (!filep)
 154                err(1, "%s: open failed", path);
 155
 156        return filep;
 157}
 158
 159/* Parse a file containing a single int */
 160static int parse_int_file(int fatal, const char *fmt, ...)
 161{
 162        va_list args;
 163        char path[PATH_MAX];
 164        FILE *filep;
 165        int value;
 166
 167        va_start(args, fmt);
 168        vsnprintf(path, sizeof(path), fmt, args);
 169        va_end(args);
 170        if (fatal) {
 171                filep = fopen_or_exit(path, "r");
 172        } else {
 173                filep = fopen(path, "r");
 174                if (!filep)
 175                        return -1;
 176        }
 177        if (fscanf(filep, "%d", &value) != 1)
 178                err(1, "%s: failed to parse number from file", path);
 179        fclose(filep);
 180
 181        return value;
 182}
 183
 184int cpufreq_sysfs_present(void)
 185{
 186        DIR *dir;
 187
 188        dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq");
 189        if (dir) {
 190                closedir(dir);
 191                return 1;
 192        }
 193
 194        return 0;
 195}
 196
 197int out_format_is_json(void)
 198{
 199        return out_format_json;
 200}
 201
 202static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id)
 203{
 204        const char *pathname = "/var/run/isst_cpu_topology.dat";
 205        struct cpu_topology cpu_top;
 206        FILE *fp;
 207        int ret;
 208
 209        fp = fopen(pathname, "rb");
 210        if (!fp)
 211                return -1;
 212
 213        ret = fseek(fp, cpu * sizeof(cpu_top), SEEK_SET);
 214        if (ret)
 215                goto err_ret;
 216
 217        ret = fread(&cpu_top, sizeof(cpu_top), 1, fp);
 218        if (ret != 1) {
 219                ret = -1;
 220                goto err_ret;
 221        }
 222
 223        *pkg_id = cpu_top.pkg_id;
 224        *core_id = cpu_top.core_id;
 225        *die_id = cpu_top.die_id;
 226        ret = 0;
 227
 228err_ret:
 229        fclose(fp);
 230
 231        return ret;
 232}
 233
 234static void store_cpu_topology(void)
 235{
 236        const char *pathname = "/var/run/isst_cpu_topology.dat";
 237        FILE *fp;
 238        int i;
 239
 240        fp = fopen(pathname, "rb");
 241        if (fp) {
 242                /* Mapping already exists */
 243                fclose(fp);
 244                return;
 245        }
 246
 247        fp = fopen(pathname, "wb");
 248        if (!fp) {
 249                fprintf(stderr, "Can't create file:%s\n", pathname);
 250                return;
 251        }
 252
 253        fprintf(stderr, "Caching topology information\n");
 254
 255        for (i = 0; i < topo_max_cpus; ++i) {
 256                struct cpu_topology cpu_top;
 257
 258                cpu_top.core_id = parse_int_file(0,
 259                        "/sys/devices/system/cpu/cpu%d/topology/core_id", i);
 260                if (cpu_top.core_id < 0)
 261                        cpu_top.core_id = -1;
 262
 263                cpu_top.pkg_id = parse_int_file(0,
 264                        "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
 265                if (cpu_top.pkg_id < 0)
 266                        cpu_top.pkg_id = -1;
 267
 268                cpu_top.die_id = parse_int_file(0,
 269                        "/sys/devices/system/cpu/cpu%d/topology/die_id", i);
 270                if (cpu_top.die_id < 0)
 271                        cpu_top.die_id = -1;
 272
 273                cpu_top.cpu = i;
 274
 275                if (fwrite(&cpu_top, sizeof(cpu_top), 1, fp) != 1) {
 276                        fprintf(stderr, "Can't write to:%s\n", pathname);
 277                        break;
 278                }
 279        }
 280
 281        fclose(fp);
 282}
 283
 284int get_physical_package_id(int cpu)
 285{
 286        int ret;
 287
 288        ret = parse_int_file(0,
 289                        "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
 290                        cpu);
 291        if (ret < 0) {
 292                int core_id, pkg_id, die_id;
 293
 294                ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
 295                if (!ret)
 296                        return pkg_id;
 297        }
 298
 299        return ret;
 300}
 301
 302int get_physical_core_id(int cpu)
 303{
 304        int ret;
 305
 306        ret = parse_int_file(0,
 307                        "/sys/devices/system/cpu/cpu%d/topology/core_id",
 308                        cpu);
 309        if (ret < 0) {
 310                int core_id, pkg_id, die_id;
 311
 312                ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
 313                if (!ret)
 314                        return core_id;
 315        }
 316
 317        return ret;
 318}
 319
 320int get_physical_die_id(int cpu)
 321{
 322        int ret;
 323
 324        ret = parse_int_file(0,
 325                        "/sys/devices/system/cpu/cpu%d/topology/die_id",
 326                        cpu);
 327        if (ret < 0) {
 328                int core_id, pkg_id, die_id;
 329
 330                ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
 331                if (!ret)
 332                        return die_id;
 333        }
 334
 335        if (ret < 0)
 336                ret = 0;
 337
 338        return ret;
 339}
 340
 341int get_cpufreq_base_freq(int cpu)
 342{
 343        return parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", cpu);
 344}
 345
 346int get_topo_max_cpus(void)
 347{
 348        return topo_max_cpus;
 349}
 350
 351static void set_cpu_online_offline(int cpu, int state)
 352{
 353        char buffer[128];
 354        int fd, ret;
 355
 356        snprintf(buffer, sizeof(buffer),
 357                 "/sys/devices/system/cpu/cpu%d/online", cpu);
 358
 359        fd = open(buffer, O_WRONLY);
 360        if (fd < 0) {
 361                if (!cpu && state) {
 362                        fprintf(stderr, "This system is not configured for CPU 0 online/offline\n");
 363                        fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n");
 364                        return;
 365                }
 366                err(-1, "%s open failed", buffer);
 367        }
 368
 369        if (state)
 370                ret = write(fd, "1\n", 2);
 371        else
 372                ret = write(fd, "0\n", 2);
 373
 374        if (ret == -1)
 375                perror("Online/Offline: Operation failed\n");
 376
 377        close(fd);
 378}
 379
 380#define MAX_PACKAGE_COUNT 8
 381#define MAX_DIE_PER_PACKAGE 2
 382static void for_each_online_package_in_set(void (*callback)(int, void *, void *,
 383                                                            void *, void *),
 384                                           void *arg1, void *arg2, void *arg3,
 385                                           void *arg4)
 386{
 387        int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT];
 388        int pkg_index = 0, i;
 389
 390        memset(max_packages, 0xff, sizeof(max_packages));
 391        for (i = 0; i < topo_max_cpus; ++i) {
 392                int j, online, pkg_id, die_id = 0, skip = 0;
 393
 394                if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
 395                        continue;
 396                if (i)
 397                        online = parse_int_file(
 398                                1, "/sys/devices/system/cpu/cpu%d/online", i);
 399                else
 400                        online =
 401                                1; /* online entry for CPU 0 needs some special configs */
 402
 403                die_id = get_physical_die_id(i);
 404                if (die_id < 0)
 405                        die_id = 0;
 406
 407                pkg_id = parse_int_file(0,
 408                        "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
 409                if (pkg_id < 0)
 410                        continue;
 411
 412                /* Create an unique id for package, die combination to store */
 413                pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
 414
 415                for (j = 0; j < pkg_index; ++j) {
 416                        if (max_packages[j] == pkg_id) {
 417                                skip = 1;
 418                                break;
 419                        }
 420                }
 421
 422                if (!skip && online && callback) {
 423                        callback(i, arg1, arg2, arg3, arg4);
 424                        max_packages[pkg_index++] = pkg_id;
 425                }
 426        }
 427}
 428
 429static void for_each_online_target_cpu_in_set(
 430        void (*callback)(int, void *, void *, void *, void *), void *arg1,
 431        void *arg2, void *arg3, void *arg4)
 432{
 433        int i, found = 0;
 434
 435        for (i = 0; i < topo_max_cpus; ++i) {
 436                int online;
 437
 438                if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
 439                        continue;
 440                if (i)
 441                        online = parse_int_file(
 442                                1, "/sys/devices/system/cpu/cpu%d/online", i);
 443                else
 444                        online =
 445                                1; /* online entry for CPU 0 needs some special configs */
 446
 447                if (online && callback) {
 448                        callback(i, arg1, arg2, arg3, arg4);
 449                        found = 1;
 450                }
 451        }
 452
 453        if (!found)
 454                fprintf(stderr, "No valid CPU in the list\n");
 455}
 456
 457#define BITMASK_SIZE 32
 458static void set_max_cpu_num(void)
 459{
 460        FILE *filep;
 461        unsigned long dummy;
 462        int i;
 463
 464        topo_max_cpus = 0;
 465        for (i = 0; i < 256; ++i) {
 466                char path[256];
 467
 468                snprintf(path, sizeof(path),
 469                         "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
 470                filep = fopen(path, "r");
 471                if (filep)
 472                        break;
 473        }
 474
 475        if (!filep) {
 476                fprintf(stderr, "Can't get max cpu number\n");
 477                exit(0);
 478        }
 479
 480        while (fscanf(filep, "%lx,", &dummy) == 1)
 481                topo_max_cpus += BITMASK_SIZE;
 482        fclose(filep);
 483
 484        debug_printf("max cpus %d\n", topo_max_cpus);
 485}
 486
 487size_t alloc_cpu_set(cpu_set_t **cpu_set)
 488{
 489        cpu_set_t *_cpu_set;
 490        size_t size;
 491
 492        _cpu_set = CPU_ALLOC((topo_max_cpus + 1));
 493        if (_cpu_set == NULL)
 494                err(3, "CPU_ALLOC");
 495        size = CPU_ALLOC_SIZE((topo_max_cpus + 1));
 496        CPU_ZERO_S(size, _cpu_set);
 497
 498        *cpu_set = _cpu_set;
 499        return size;
 500}
 501
 502void free_cpu_set(cpu_set_t *cpu_set)
 503{
 504        CPU_FREE(cpu_set);
 505}
 506
 507static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
 508static long long core_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
 509static void set_cpu_present_cpu_mask(void)
 510{
 511        size_t size;
 512        DIR *dir;
 513        int i;
 514
 515        size = alloc_cpu_set(&present_cpumask);
 516        present_cpumask_size = size;
 517        for (i = 0; i < topo_max_cpus; ++i) {
 518                char buffer[256];
 519
 520                snprintf(buffer, sizeof(buffer),
 521                         "/sys/devices/system/cpu/cpu%d", i);
 522                dir = opendir(buffer);
 523                if (dir) {
 524                        int pkg_id, die_id;
 525
 526                        CPU_SET_S(i, size, present_cpumask);
 527                        die_id = get_physical_die_id(i);
 528                        if (die_id < 0)
 529                                die_id = 0;
 530
 531                        pkg_id = get_physical_package_id(i);
 532                        if (pkg_id < 0) {
 533                                fprintf(stderr, "Failed to get package id, CPU %d may be offline\n", i);
 534                                continue;
 535                        }
 536                        if (pkg_id < MAX_PACKAGE_COUNT &&
 537                            die_id < MAX_DIE_PER_PACKAGE) {
 538                                int core_id = get_physical_core_id(i);
 539
 540                                cpu_cnt[pkg_id][die_id]++;
 541                                core_mask[pkg_id][die_id] |= (1ULL << core_id);
 542                        }
 543                }
 544                closedir(dir);
 545        }
 546}
 547
 548int get_core_count(int pkg_id, int die_id)
 549{
 550        int cnt = 0;
 551
 552        if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE) {
 553                int i;
 554
 555                for (i = 0; i < sizeof(long long) * 8; ++i) {
 556                        if (core_mask[pkg_id][die_id] & (1ULL << i))
 557                                cnt++;
 558                }
 559        }
 560
 561        return cnt;
 562}
 563
 564int get_cpu_count(int pkg_id, int die_id)
 565{
 566        if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
 567                return cpu_cnt[pkg_id][die_id];
 568
 569        return 0;
 570}
 571
 572static void set_cpu_target_cpu_mask(void)
 573{
 574        size_t size;
 575        int i;
 576
 577        size = alloc_cpu_set(&target_cpumask);
 578        target_cpumask_size = size;
 579        for (i = 0; i < max_target_cpus; ++i) {
 580                if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size,
 581                                 present_cpumask))
 582                        continue;
 583
 584                CPU_SET_S(target_cpus[i], size, target_cpumask);
 585        }
 586}
 587
 588static void create_cpu_map(void)
 589{
 590        const char *pathname = "/dev/isst_interface";
 591        int i, fd = 0;
 592        struct isst_if_cpu_maps map;
 593
 594        cpu_map = malloc(sizeof(*cpu_map) * topo_max_cpus);
 595        if (!cpu_map)
 596                err(3, "cpumap");
 597
 598        fd = open(pathname, O_RDWR);
 599        if (fd < 0)
 600                err(-1, "%s open failed", pathname);
 601
 602        for (i = 0; i < topo_max_cpus; ++i) {
 603                if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
 604                        continue;
 605
 606                map.cmd_count = 1;
 607                map.cpu_map[0].logical_cpu = i;
 608
 609                debug_printf(" map logical_cpu:%d\n",
 610                             map.cpu_map[0].logical_cpu);
 611                if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
 612                        perror("ISST_IF_GET_PHY_ID");
 613                        fprintf(outf, "Error: map logical_cpu:%d\n",
 614                                map.cpu_map[0].logical_cpu);
 615                        continue;
 616                }
 617                cpu_map[i].core_id = get_physical_core_id(i);
 618                cpu_map[i].pkg_id = get_physical_package_id(i);
 619                cpu_map[i].die_id = get_physical_die_id(i);
 620                cpu_map[i].punit_cpu = map.cpu_map[0].physical_cpu;
 621                cpu_map[i].punit_cpu_core = (map.cpu_map[0].physical_cpu >>
 622                                             1); // shift to get core id
 623
 624                debug_printf(
 625                        "map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n",
 626                        i, cpu_map[i].core_id, cpu_map[i].die_id,
 627                        cpu_map[i].pkg_id, cpu_map[i].punit_cpu,
 628                        cpu_map[i].punit_cpu_core);
 629        }
 630
 631        if (fd)
 632                close(fd);
 633}
 634
 635int find_logical_cpu(int pkg_id, int die_id, int punit_core_id)
 636{
 637        int i;
 638
 639        for (i = 0; i < topo_max_cpus; ++i) {
 640                if (cpu_map[i].pkg_id == pkg_id &&
 641                    cpu_map[i].die_id == die_id &&
 642                    cpu_map[i].punit_cpu_core == punit_core_id)
 643                        return i;
 644        }
 645
 646        return -EINVAL;
 647}
 648
 649void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask,
 650                                      size_t core_cpumask_size,
 651                                      cpu_set_t *core_cpumask, int *cpu_cnt)
 652{
 653        int i, cnt = 0;
 654        int die_id, pkg_id;
 655
 656        *cpu_cnt = 0;
 657        die_id = get_physical_die_id(cpu);
 658        pkg_id = get_physical_package_id(cpu);
 659
 660        for (i = 0; i < 64; ++i) {
 661                if (core_mask & BIT_ULL(i)) {
 662                        int j;
 663
 664                        for (j = 0; j < topo_max_cpus; ++j) {
 665                                if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask))
 666                                        continue;
 667
 668                                if (cpu_map[j].pkg_id == pkg_id &&
 669                                    cpu_map[j].die_id == die_id &&
 670                                    cpu_map[j].punit_cpu_core == i) {
 671                                        CPU_SET_S(j, core_cpumask_size,
 672                                                  core_cpumask);
 673                                        ++cnt;
 674                                }
 675                        }
 676                }
 677        }
 678
 679        *cpu_cnt = cnt;
 680}
 681
 682int find_phy_core_num(int logical_cpu)
 683{
 684        if (logical_cpu < topo_max_cpus)
 685                return cpu_map[logical_cpu].punit_cpu_core;
 686
 687        return -EINVAL;
 688}
 689
 690static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
 691                                  unsigned int *value)
 692{
 693        struct isst_if_io_regs io_regs;
 694        const char *pathname = "/dev/isst_interface";
 695        int cmd;
 696        int fd;
 697
 698        debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
 699
 700        fd = open(pathname, O_RDWR);
 701        if (fd < 0)
 702                err(-1, "%s open failed", pathname);
 703
 704        io_regs.req_count = 1;
 705        io_regs.io_reg[0].logical_cpu = cpu;
 706        io_regs.io_reg[0].reg = reg;
 707        cmd = ISST_IF_IO_CMD;
 708        if (write) {
 709                io_regs.io_reg[0].read_write = 1;
 710                io_regs.io_reg[0].value = *value;
 711        } else {
 712                io_regs.io_reg[0].read_write = 0;
 713        }
 714
 715        if (ioctl(fd, cmd, &io_regs) == -1) {
 716                if (errno == ENOTTY) {
 717                        perror("ISST_IF_IO_COMMAND\n");
 718                        fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
 719                        exit(0);
 720                }
 721                fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
 722                        cpu, reg, write);
 723        } else {
 724                if (!write)
 725                        *value = io_regs.io_reg[0].value;
 726
 727                debug_printf(
 728                        "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
 729                        cpu, reg, write, *value);
 730        }
 731
 732        close(fd);
 733
 734        return 0;
 735}
 736
 737int isst_send_mbox_command(unsigned int cpu, unsigned char command,
 738                           unsigned char sub_command, unsigned int parameter,
 739                           unsigned int req_data, unsigned int *resp)
 740{
 741        const char *pathname = "/dev/isst_interface";
 742        int fd, retry;
 743        struct isst_if_mbox_cmds mbox_cmds = { 0 };
 744
 745        debug_printf(
 746                "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
 747                cpu, command, sub_command, parameter, req_data);
 748
 749        if (!is_skx_based_platform() && command == CONFIG_CLOS &&
 750            sub_command != CLOS_PM_QOS_CONFIG) {
 751                unsigned int value;
 752                int write = 0;
 753                int clos_id, core_id, ret = 0;
 754
 755                debug_printf("CPU %d\n", cpu);
 756
 757                if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
 758                        value = req_data;
 759                        write = 1;
 760                }
 761
 762                switch (sub_command) {
 763                case CLOS_PQR_ASSOC:
 764                        core_id = parameter & 0xff;
 765                        ret = isst_send_mmio_command(
 766                                cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
 767                                &value);
 768                        if (!ret && !write)
 769                                *resp = value;
 770                        break;
 771                case CLOS_PM_CLOS:
 772                        clos_id = parameter & 0x03;
 773                        ret = isst_send_mmio_command(
 774                                cpu, PM_CLOS_OFFSET + clos_id * 4, write,
 775                                &value);
 776                        if (!ret && !write)
 777                                *resp = value;
 778                        break;
 779                case CLOS_STATUS:
 780                        break;
 781                default:
 782                        break;
 783                }
 784                return ret;
 785        }
 786
 787        mbox_cmds.cmd_count = 1;
 788        mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
 789        mbox_cmds.mbox_cmd[0].command = command;
 790        mbox_cmds.mbox_cmd[0].sub_command = sub_command;
 791        mbox_cmds.mbox_cmd[0].parameter = parameter;
 792        mbox_cmds.mbox_cmd[0].req_data = req_data;
 793
 794        if (mbox_delay)
 795                usleep(mbox_delay * 1000);
 796
 797        fd = open(pathname, O_RDWR);
 798        if (fd < 0)
 799                err(-1, "%s open failed", pathname);
 800
 801        retry = mbox_retries;
 802
 803        do {
 804                if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
 805                        if (errno == ENOTTY) {
 806                                perror("ISST_IF_MBOX_COMMAND\n");
 807                                fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
 808                                exit(0);
 809                        }
 810                        debug_printf(
 811                                "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
 812                                cpu, command, sub_command, parameter, req_data, errno);
 813                        --retry;
 814                } else {
 815                        *resp = mbox_cmds.mbox_cmd[0].resp_data;
 816                        debug_printf(
 817                                "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
 818                                cpu, command, sub_command, parameter, req_data, *resp);
 819                        break;
 820                }
 821        } while (retry);
 822
 823        close(fd);
 824
 825        if (!retry) {
 826                debug_printf("Failed mbox command even after retries\n");
 827                return -1;
 828
 829        }
 830        return 0;
 831}
 832
 833int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
 834                          unsigned long long *req_resp)
 835{
 836        struct isst_if_msr_cmds msr_cmds;
 837        const char *pathname = "/dev/isst_interface";
 838        int fd;
 839
 840        fd = open(pathname, O_RDWR);
 841        if (fd < 0)
 842                err(-1, "%s open failed", pathname);
 843
 844        msr_cmds.cmd_count = 1;
 845        msr_cmds.msr_cmd[0].logical_cpu = cpu;
 846        msr_cmds.msr_cmd[0].msr = msr;
 847        msr_cmds.msr_cmd[0].read_write = write;
 848        if (write)
 849                msr_cmds.msr_cmd[0].data = *req_resp;
 850
 851        if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
 852                perror("ISST_IF_MSR_COMMAND");
 853                fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
 854                        cpu, msr, write);
 855        } else {
 856                if (!write)
 857                        *req_resp = msr_cmds.msr_cmd[0].data;
 858
 859                debug_printf(
 860                        "msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
 861                        cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
 862        }
 863
 864        close(fd);
 865
 866        return 0;
 867}
 868
 869static int isst_fill_platform_info(void)
 870{
 871        const char *pathname = "/dev/isst_interface";
 872        int fd;
 873
 874        fd = open(pathname, O_RDWR);
 875        if (fd < 0)
 876                err(-1, "%s open failed", pathname);
 877
 878        if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) {
 879                perror("ISST_IF_GET_PLATFORM_INFO");
 880                close(fd);
 881                return -1;
 882        }
 883
 884        close(fd);
 885
 886        if (isst_platform_info.api_version > supported_api_ver) {
 887                printf("Incompatible API versions; Upgrade of tool is required\n");
 888                return -1;
 889        }
 890        return 0;
 891}
 892
 893static void isst_print_extended_platform_info(void)
 894{
 895        int cp_state, cp_cap, fact_support = 0, pbf_support = 0;
 896        struct isst_pkg_ctdp_level_info ctdp_level;
 897        struct isst_pkg_ctdp pkg_dev;
 898        int ret, i, j;
 899        FILE *filep;
 900
 901        for (i = 0; i < 256; ++i) {
 902                char path[256];
 903
 904                snprintf(path, sizeof(path),
 905                         "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
 906                filep = fopen(path, "r");
 907                if (filep)
 908                        break;
 909        }
 910
 911        if (!filep)
 912                return;
 913
 914        fclose(filep);
 915
 916        ret = isst_get_ctdp_levels(i, &pkg_dev);
 917        if (ret)
 918                return;
 919
 920        if (pkg_dev.enabled) {
 921                fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n");
 922        } else {
 923                fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n");
 924                fprintf(outf, "Only performance level 0 (base level) is present\n");
 925        }
 926
 927        if (pkg_dev.locked)
 928                fprintf(outf, "TDP level change control is locked\n");
 929        else
 930                fprintf(outf, "TDP level change control is unlocked, max level: %d \n", pkg_dev.levels);
 931
 932        for (j = 0; j <= pkg_dev.levels; ++j) {
 933                ret = isst_get_ctdp_control(i, j, &ctdp_level);
 934                if (ret)
 935                        continue;
 936
 937                if (!fact_support && ctdp_level.fact_support)
 938                        fact_support = 1;
 939
 940                if (!pbf_support && ctdp_level.pbf_support)
 941                        pbf_support = 1;
 942        }
 943
 944        if (fact_support)
 945                fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n");
 946        else
 947                fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n");
 948
 949        if (pbf_support)
 950                fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n");
 951        else
 952                fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n");
 953
 954        ret = isst_read_pm_config(i, &cp_state, &cp_cap);
 955        if (cp_cap)
 956                fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n");
 957        else
 958                fprintf(outf, "Intel(R) SST-CP (feature core-power) is not supported\n");
 959}
 960
 961static void isst_print_platform_information(void)
 962{
 963        struct isst_if_platform_info platform_info;
 964        const char *pathname = "/dev/isst_interface";
 965        int fd;
 966
 967        if (is_clx_n_platform()) {
 968                fprintf(stderr, "\nThis option in not supported on this platform\n");
 969                exit(0);
 970        }
 971
 972        fd = open(pathname, O_RDWR);
 973        if (fd < 0)
 974                err(-1, "%s open failed", pathname);
 975
 976        if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) {
 977                perror("ISST_IF_GET_PLATFORM_INFO");
 978        } else {
 979                fprintf(outf, "Platform: API version : %d\n",
 980                        platform_info.api_version);
 981                fprintf(outf, "Platform: Driver version : %d\n",
 982                        platform_info.driver_version);
 983                fprintf(outf, "Platform: mbox supported : %d\n",
 984                        platform_info.mbox_supported);
 985                fprintf(outf, "Platform: mmio supported : %d\n",
 986                        platform_info.mmio_supported);
 987                isst_print_extended_platform_info();
 988        }
 989
 990        close(fd);
 991
 992        exit(0);
 993}
 994
 995static char *local_str0, *local_str1;
 996static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
 997                                 void *arg4)
 998{
 999        int (*fn_ptr)(int cpu, void *arg);
1000        int ret;
1001
1002        fn_ptr = arg1;
1003        ret = fn_ptr(cpu, arg2);
1004        if (ret)
1005                isst_display_error_info_message(1, "get_tdp_* failed", 0, 0);
1006        else
1007                isst_ctdp_display_core_info(cpu, outf, arg3,
1008                                            *(unsigned int *)arg4,
1009                                            local_str0, local_str1);
1010}
1011
1012#define _get_tdp_level(desc, suffix, object, help, str0, str1)                  \
1013        static void get_tdp_##object(int arg)                                    \
1014        {                                                                         \
1015                struct isst_pkg_ctdp ctdp;                                        \
1016\
1017                if (cmd_help) {                                                   \
1018                        fprintf(stderr,                                           \
1019                                "Print %s [No command arguments are required]\n", \
1020                                help);                                            \
1021                        exit(0);                                                  \
1022                }                                                                 \
1023                local_str0 = str0;                                                \
1024                local_str1 = str1;                                                \
1025                isst_ctdp_display_information_start(outf);                        \
1026                if (max_target_cpus)                                              \
1027                        for_each_online_target_cpu_in_set(                        \
1028                                exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix,     \
1029                                &ctdp, desc, &ctdp.object);                       \
1030                else                                                              \
1031                        for_each_online_package_in_set(exec_on_get_ctdp_cpu,      \
1032                                                       isst_get_ctdp_##suffix,    \
1033                                                       &ctdp, desc,               \
1034                                                       &ctdp.object);             \
1035                isst_ctdp_display_information_end(outf);                          \
1036        }
1037
1038_get_tdp_level("get-config-levels", levels, levels, "Max TDP level", NULL, NULL);
1039_get_tdp_level("get-config-version", levels, version, "TDP version", NULL, NULL);
1040_get_tdp_level("get-config-enabled", levels, enabled, "perf-profile enable status", "disabled", "enabled");
1041_get_tdp_level("get-config-current_level", levels, current_level,
1042               "Current TDP Level", NULL, NULL);
1043_get_tdp_level("get-lock-status", levels, locked, "TDP lock status", "unlocked", "locked");
1044
1045struct isst_pkg_ctdp clx_n_pkg_dev;
1046
1047static int clx_n_get_base_ratio(void)
1048{
1049        FILE *fp;
1050        char *begin, *end, *line = NULL;
1051        char number[5];
1052        float value = 0;
1053        size_t n = 0;
1054
1055        fp = fopen("/proc/cpuinfo", "r");
1056        if (!fp)
1057                err(-1, "cannot open /proc/cpuinfo\n");
1058
1059        while (getline(&line, &n, fp) > 0) {
1060                if (strstr(line, "model name")) {
1061                        /* this is true for CascadeLake-N */
1062                        begin = strstr(line, "@ ") + 2;
1063                        end = strstr(line, "GHz");
1064                        strncpy(number, begin, end - begin);
1065                        value = atof(number) * 10;
1066                        break;
1067                }
1068        }
1069        free(line);
1070        fclose(fp);
1071
1072        return (int)(value);
1073}
1074
1075static int clx_n_config(int cpu)
1076{
1077        int i, ret, pkg_id, die_id;
1078        unsigned long cpu_bf;
1079        struct isst_pkg_ctdp_level_info *ctdp_level;
1080        struct isst_pbf_info *pbf_info;
1081
1082        ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1083        pbf_info = &ctdp_level->pbf_info;
1084        ctdp_level->core_cpumask_size =
1085                        alloc_cpu_set(&ctdp_level->core_cpumask);
1086
1087        /* find the frequency base ratio */
1088        ctdp_level->tdp_ratio = clx_n_get_base_ratio();
1089        if (ctdp_level->tdp_ratio == 0) {
1090                debug_printf("CLX: cn base ratio is zero\n");
1091                ret = -1;
1092                goto error_ret;
1093        }
1094
1095        /* find the high and low priority frequencies */
1096        pbf_info->p1_high = 0;
1097        pbf_info->p1_low = ~0;
1098
1099        pkg_id = get_physical_package_id(cpu);
1100        die_id = get_physical_die_id(cpu);
1101
1102        for (i = 0; i < topo_max_cpus; i++) {
1103                if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
1104                        continue;
1105
1106                if (pkg_id != get_physical_package_id(i) ||
1107                    die_id != get_physical_die_id(i))
1108                        continue;
1109
1110                CPU_SET_S(i, ctdp_level->core_cpumask_size,
1111                          ctdp_level->core_cpumask);
1112
1113                cpu_bf = parse_int_file(1,
1114                        "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
1115                                        i);
1116                if (cpu_bf > pbf_info->p1_high)
1117                        pbf_info->p1_high = cpu_bf;
1118                if (cpu_bf < pbf_info->p1_low)
1119                        pbf_info->p1_low = cpu_bf;
1120        }
1121
1122        if (pbf_info->p1_high == ~0UL) {
1123                debug_printf("CLX: maximum base frequency not set\n");
1124                ret = -1;
1125                goto error_ret;
1126        }
1127
1128        if (pbf_info->p1_low == 0) {
1129                debug_printf("CLX: minimum base frequency not set\n");
1130                ret = -1;
1131                goto error_ret;
1132        }
1133
1134        /* convert frequencies back to ratios */
1135        pbf_info->p1_high = pbf_info->p1_high / 100000;
1136        pbf_info->p1_low = pbf_info->p1_low / 100000;
1137
1138        /* create high priority cpu mask */
1139        pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
1140        for (i = 0; i < topo_max_cpus; i++) {
1141                if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
1142                        continue;
1143
1144                if (pkg_id != get_physical_package_id(i) ||
1145                    die_id != get_physical_die_id(i))
1146                        continue;
1147
1148                cpu_bf = parse_int_file(1,
1149                        "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
1150                                        i);
1151                cpu_bf = cpu_bf / 100000;
1152                if (cpu_bf == pbf_info->p1_high)
1153                        CPU_SET_S(i, pbf_info->core_cpumask_size,
1154                                  pbf_info->core_cpumask);
1155        }
1156
1157        /* extra ctdp & pbf struct parameters */
1158        ctdp_level->processed = 1;
1159        ctdp_level->pbf_support = 1; /* PBF is always supported and enabled */
1160        ctdp_level->pbf_enabled = 1;
1161        ctdp_level->fact_support = 0; /* FACT is never supported */
1162        ctdp_level->fact_enabled = 0;
1163
1164        return 0;
1165
1166error_ret:
1167        free_cpu_set(ctdp_level->core_cpumask);
1168        return ret;
1169}
1170
1171static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2,
1172                                   void *arg3, void *arg4)
1173{
1174        int ret;
1175
1176        if (tdp_level != 0xff && tdp_level != 0) {
1177                isst_display_error_info_message(1, "Invalid level", 1, tdp_level);
1178                exit(0);
1179        }
1180
1181        ret = clx_n_config(cpu);
1182        if (ret) {
1183                debug_printf("clx_n_config failed");
1184        } else {
1185                struct isst_pkg_ctdp_level_info *ctdp_level;
1186                struct isst_pbf_info *pbf_info;
1187
1188                ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1189                pbf_info = &ctdp_level->pbf_info;
1190                clx_n_pkg_dev.processed = 1;
1191                isst_ctdp_display_information(cpu, outf, tdp_level, &clx_n_pkg_dev);
1192                free_cpu_set(ctdp_level->core_cpumask);
1193                free_cpu_set(pbf_info->core_cpumask);
1194        }
1195}
1196
1197static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2,
1198                                     void *arg3, void *arg4)
1199{
1200        struct isst_pkg_ctdp pkg_dev;
1201        int ret;
1202
1203        memset(&pkg_dev, 0, sizeof(pkg_dev));
1204        ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev);
1205        if (ret) {
1206                isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, cpu);
1207                isst_ctdp_display_information_end(outf);
1208                exit(1);
1209        } else {
1210                isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev);
1211                isst_get_process_ctdp_complete(cpu, &pkg_dev);
1212        }
1213}
1214
1215static void dump_isst_config(int arg)
1216{
1217        void *fn;
1218
1219        if (cmd_help) {
1220                fprintf(stderr,
1221                        "Print Intel(R) Speed Select Technology Performance profile configuration\n");
1222                fprintf(stderr,
1223                        "including base frequency and turbo frequency configurations\n");
1224                fprintf(stderr, "Optional: -l|--level : Specify tdp level\n");
1225                fprintf(stderr,
1226                        "\tIf no arguments, dump information for all TDP levels\n");
1227                exit(0);
1228        }
1229
1230        if (!is_clx_n_platform())
1231                fn = dump_isst_config_for_cpu;
1232        else
1233                fn = dump_clx_n_config_for_cpu;
1234
1235        isst_ctdp_display_information_start(outf);
1236
1237        if (max_target_cpus)
1238                for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
1239        else
1240                for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
1241
1242        isst_ctdp_display_information_end(outf);
1243}
1244
1245static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1246                                  void *arg4)
1247{
1248        int ret;
1249
1250        ret = isst_set_tdp_level(cpu, tdp_level);
1251        if (ret) {
1252                isst_display_error_info_message(1, "Set TDP level failed", 0, 0);
1253                isst_ctdp_display_information_end(outf);
1254                exit(1);
1255        } else {
1256                isst_display_result(cpu, outf, "perf-profile", "set_tdp_level",
1257                                    ret);
1258                if (force_online_offline) {
1259                        struct isst_pkg_ctdp_level_info ctdp_level;
1260                        int pkg_id = get_physical_package_id(cpu);
1261                        int die_id = get_physical_die_id(cpu);
1262
1263                        fprintf(stderr, "Option is set to online/offline\n");
1264                        ctdp_level.core_cpumask_size =
1265                                alloc_cpu_set(&ctdp_level.core_cpumask);
1266                        ret = isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
1267                        if (ret) {
1268                                isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
1269                                return;
1270                        }
1271                        if (ctdp_level.cpu_count) {
1272                                int i, max_cpus = get_topo_max_cpus();
1273                                for (i = 0; i < max_cpus; ++i) {
1274                                        if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i))
1275                                                continue;
1276                                        if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
1277                                                fprintf(stderr, "online cpu %d\n", i);
1278                                                set_cpu_online_offline(i, 1);
1279                                        } else {
1280                                                fprintf(stderr, "offline cpu %d\n", i);
1281                                                set_cpu_online_offline(i, 0);
1282                                        }
1283                                }
1284                        }
1285                }
1286        }
1287}
1288
1289static void set_tdp_level(int arg)
1290{
1291        if (cmd_help) {
1292                fprintf(stderr, "Set Config TDP level\n");
1293                fprintf(stderr,
1294                        "\t Arguments: -l|--level : Specify tdp level\n");
1295                fprintf(stderr,
1296                        "\t Optional Arguments: -o | online : online/offline for the tdp level\n");
1297                fprintf(stderr,
1298                        "\t  online/offline operation has limitations, refer to Linux hotplug documentation\n");
1299                exit(0);
1300        }
1301
1302        if (tdp_level == 0xff) {
1303                isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
1304                exit(1);
1305        }
1306        isst_ctdp_display_information_start(outf);
1307        if (max_target_cpus)
1308                for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
1309                                                  NULL, NULL, NULL);
1310        else
1311                for_each_online_package_in_set(set_tdp_level_for_cpu, NULL,
1312                                               NULL, NULL, NULL);
1313        isst_ctdp_display_information_end(outf);
1314}
1315
1316static void clx_n_dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2,
1317                                       void *arg3, void *arg4)
1318{
1319        int ret;
1320
1321        ret = clx_n_config(cpu);
1322        if (ret) {
1323                isst_display_error_info_message(1, "clx_n_config failed", 0, 0);
1324        } else {
1325                struct isst_pkg_ctdp_level_info *ctdp_level;
1326                struct isst_pbf_info *pbf_info;
1327
1328                ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1329                pbf_info = &ctdp_level->pbf_info;
1330                isst_pbf_display_information(cpu, outf, tdp_level, pbf_info);
1331                free_cpu_set(ctdp_level->core_cpumask);
1332                free_cpu_set(pbf_info->core_cpumask);
1333        }
1334}
1335
1336static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1337                                    void *arg4)
1338{
1339        struct isst_pbf_info pbf_info;
1340        int ret;
1341
1342        ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info);
1343        if (ret) {
1344                isst_display_error_info_message(1, "Failed to get base-freq info at this level", 1, tdp_level);
1345                isst_ctdp_display_information_end(outf);
1346                exit(1);
1347        } else {
1348                isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info);
1349                isst_get_pbf_info_complete(&pbf_info);
1350        }
1351}
1352
1353static void dump_pbf_config(int arg)
1354{
1355        void *fn;
1356
1357        if (cmd_help) {
1358                fprintf(stderr,
1359                        "Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n");
1360                fprintf(stderr,
1361                        "\tArguments: -l|--level : Specify tdp level\n");
1362                exit(0);
1363        }
1364
1365        if (tdp_level == 0xff) {
1366                isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
1367                exit(1);
1368        }
1369
1370        if (!is_clx_n_platform())
1371                fn = dump_pbf_config_for_cpu;
1372        else
1373                fn = clx_n_dump_pbf_config_for_cpu;
1374
1375        isst_ctdp_display_information_start(outf);
1376
1377        if (max_target_cpus)
1378                for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
1379        else
1380                for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
1381
1382        isst_ctdp_display_information_end(outf);
1383}
1384
1385static int set_clos_param(int cpu, int clos, int epp, int wt, int min, int max)
1386{
1387        struct isst_clos_config clos_config;
1388        int ret;
1389
1390        ret = isst_pm_get_clos(cpu, clos, &clos_config);
1391        if (ret) {
1392                isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
1393                return ret;
1394        }
1395        clos_config.clos_min = min;
1396        clos_config.clos_max = max;
1397        clos_config.epp = epp;
1398        clos_config.clos_prop_prio = wt;
1399        ret = isst_set_clos(cpu, clos, &clos_config);
1400        if (ret) {
1401                isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
1402                return ret;
1403        }
1404
1405        return 0;
1406}
1407
1408static int set_cpufreq_scaling_min_max(int cpu, int max, int freq)
1409{
1410        char buffer[128], freq_str[16];
1411        int fd, ret, len;
1412
1413        if (max)
1414                snprintf(buffer, sizeof(buffer),
1415                         "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
1416        else
1417                snprintf(buffer, sizeof(buffer),
1418                         "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
1419
1420        fd = open(buffer, O_WRONLY);
1421        if (fd < 0)
1422                return fd;
1423
1424        snprintf(freq_str, sizeof(freq_str), "%d", freq);
1425        len = strlen(freq_str);
1426        ret = write(fd, freq_str, len);
1427        if (ret == -1) {
1428                close(fd);
1429                return ret;
1430        }
1431        close(fd);
1432
1433        return 0;
1434}
1435
1436static int set_clx_pbf_cpufreq_scaling_min_max(int cpu)
1437{
1438        struct isst_pkg_ctdp_level_info *ctdp_level;
1439        struct isst_pbf_info *pbf_info;
1440        int i, pkg_id, die_id, freq, freq_high, freq_low;
1441        int ret;
1442
1443        ret = clx_n_config(cpu);
1444        if (ret) {
1445                debug_printf("cpufreq_scaling_min_max failed for CLX");
1446                return ret;
1447        }
1448
1449        ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1450        pbf_info = &ctdp_level->pbf_info;
1451        freq_high = pbf_info->p1_high * 100000;
1452        freq_low = pbf_info->p1_low * 100000;
1453
1454        pkg_id = get_physical_package_id(cpu);
1455        die_id = get_physical_die_id(cpu);
1456        for (i = 0; i < get_topo_max_cpus(); ++i) {
1457                if (pkg_id != get_physical_package_id(i) ||
1458                    die_id != get_physical_die_id(i))
1459                        continue;
1460
1461                if (CPU_ISSET_S(i, pbf_info->core_cpumask_size,
1462                                  pbf_info->core_cpumask))
1463                        freq = freq_high;
1464                else
1465                        freq = freq_low;
1466
1467                set_cpufreq_scaling_min_max(i, 1, freq);
1468                set_cpufreq_scaling_min_max(i, 0, freq);
1469        }
1470
1471        return 0;
1472}
1473
1474static int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, int scaling_max)
1475{
1476        char buffer[128], min_freq[16];
1477        int fd, ret, len;
1478
1479        if (!CPU_ISSET_S(cpu, present_cpumask_size, present_cpumask))
1480                return -1;
1481
1482        if (cpuinfo_max)
1483                snprintf(buffer, sizeof(buffer),
1484                         "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu);
1485        else
1486                snprintf(buffer, sizeof(buffer),
1487                         "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_min_freq", cpu);
1488
1489        fd = open(buffer, O_RDONLY);
1490        if (fd < 0)
1491                return fd;
1492
1493        len = read(fd, min_freq, sizeof(min_freq));
1494        close(fd);
1495
1496        if (len < 0)
1497                return len;
1498
1499        if (scaling_max)
1500                snprintf(buffer, sizeof(buffer),
1501                         "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
1502        else
1503                snprintf(buffer, sizeof(buffer),
1504                         "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
1505
1506        fd = open(buffer, O_WRONLY);
1507        if (fd < 0)
1508                return fd;
1509
1510        len = strlen(min_freq);
1511        ret = write(fd, min_freq, len);
1512        if (ret == -1) {
1513                close(fd);
1514                return ret;
1515        }
1516        close(fd);
1517
1518        return 0;
1519}
1520
1521static void set_scaling_min_to_cpuinfo_max(int cpu)
1522{
1523        int i, pkg_id, die_id;
1524
1525        pkg_id = get_physical_package_id(cpu);
1526        die_id = get_physical_die_id(cpu);
1527        for (i = 0; i < get_topo_max_cpus(); ++i) {
1528                if (pkg_id != get_physical_package_id(i) ||
1529                    die_id != get_physical_die_id(i))
1530                        continue;
1531
1532                set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0);
1533        }
1534}
1535
1536static void set_scaling_min_to_cpuinfo_min(int cpu)
1537{
1538        int i, pkg_id, die_id;
1539
1540        pkg_id = get_physical_package_id(cpu);
1541        die_id = get_physical_die_id(cpu);
1542        for (i = 0; i < get_topo_max_cpus(); ++i) {
1543                if (pkg_id != get_physical_package_id(i) ||
1544                    die_id != get_physical_die_id(i))
1545                        continue;
1546
1547                set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0);
1548        }
1549}
1550
1551static void set_scaling_max_to_cpuinfo_max(int cpu)
1552{
1553        int i, pkg_id, die_id;
1554
1555        pkg_id = get_physical_package_id(cpu);
1556        die_id = get_physical_die_id(cpu);
1557        for (i = 0; i < get_topo_max_cpus(); ++i) {
1558                if (pkg_id != get_physical_package_id(i) ||
1559                    die_id != get_physical_die_id(i))
1560                        continue;
1561
1562                set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1);
1563        }
1564}
1565
1566static int set_core_priority_and_min(int cpu, int mask_size,
1567                                     cpu_set_t *cpu_mask, int min_high,
1568                                     int min_low)
1569{
1570        int pkg_id, die_id, ret, i;
1571
1572        if (!CPU_COUNT_S(mask_size, cpu_mask))
1573                return -1;
1574
1575        ret = set_clos_param(cpu, 0, 0, 0, min_high, 0xff);
1576        if (ret)
1577                return ret;
1578
1579        ret = set_clos_param(cpu, 1, 15, 15, min_low, 0xff);
1580        if (ret)
1581                return ret;
1582
1583        ret = set_clos_param(cpu, 2, 15, 15, min_low, 0xff);
1584        if (ret)
1585                return ret;
1586
1587        ret = set_clos_param(cpu, 3, 15, 15, min_low, 0xff);
1588        if (ret)
1589                return ret;
1590
1591        pkg_id = get_physical_package_id(cpu);
1592        die_id = get_physical_die_id(cpu);
1593        for (i = 0; i < get_topo_max_cpus(); ++i) {
1594                int clos;
1595
1596                if (pkg_id != get_physical_package_id(i) ||
1597                    die_id != get_physical_die_id(i))
1598                        continue;
1599
1600                if (CPU_ISSET_S(i, mask_size, cpu_mask))
1601                        clos = 0;
1602                else
1603                        clos = 3;
1604
1605                debug_printf("Associate cpu: %d clos: %d\n", i, clos);
1606                ret = isst_clos_associate(i, clos);
1607                if (ret) {
1608                        isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0);
1609                        return ret;
1610                }
1611        }
1612
1613        return 0;
1614}
1615
1616static int set_pbf_core_power(int cpu)
1617{
1618        struct isst_pbf_info pbf_info;
1619        struct isst_pkg_ctdp pkg_dev;
1620        int ret;
1621
1622        ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1623        if (ret) {
1624                debug_printf("isst_get_ctdp_levels failed");
1625                return ret;
1626        }
1627        debug_printf("Current_level: %d\n", pkg_dev.current_level);
1628
1629        ret = isst_get_pbf_info(cpu, pkg_dev.current_level, &pbf_info);
1630        if (ret) {
1631                debug_printf("isst_get_pbf_info failed");
1632                return ret;
1633        }
1634        debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high,
1635                     pbf_info.p1_low);
1636
1637        ret = set_core_priority_and_min(cpu, pbf_info.core_cpumask_size,
1638                                        pbf_info.core_cpumask,
1639                                        pbf_info.p1_high, pbf_info.p1_low);
1640        if (ret) {
1641                debug_printf("set_core_priority_and_min failed");
1642                return ret;
1643        }
1644
1645        ret = isst_pm_qos_config(cpu, 1, 1);
1646        if (ret) {
1647                debug_printf("isst_pm_qos_config failed");
1648                return ret;
1649        }
1650
1651        return 0;
1652}
1653
1654static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1655                            void *arg4)
1656{
1657        struct isst_pkg_ctdp_level_info ctdp_level;
1658        struct isst_pkg_ctdp pkg_dev;
1659        int ret;
1660        int status = *(int *)arg4;
1661
1662        if (is_clx_n_platform()) {
1663                ret = 0;
1664                if (status) {
1665                        set_clx_pbf_cpufreq_scaling_min_max(cpu);
1666
1667                } else {
1668                        set_scaling_max_to_cpuinfo_max(cpu);
1669                        set_scaling_min_to_cpuinfo_min(cpu);
1670                }
1671                goto disp_result;
1672        }
1673
1674        ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1675        if (ret) {
1676                isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
1677                goto disp_result;
1678        }
1679
1680        ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
1681        if (ret) {
1682                isst_display_error_info_message(1, "Failed to get current level", 0, 0);
1683                goto disp_result;
1684        }
1685
1686        if (!ctdp_level.pbf_support) {
1687                isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, pkg_dev.current_level);
1688                ret = -1;
1689                goto disp_result;
1690        }
1691
1692        if (auto_mode && status) {
1693                ret = set_pbf_core_power(cpu);
1694                if (ret)
1695                        goto disp_result;
1696        }
1697
1698        ret = isst_set_pbf_fact_status(cpu, 1, status);
1699        if (ret) {
1700                debug_printf("isst_set_pbf_fact_status failed");
1701                if (auto_mode)
1702                        isst_pm_qos_config(cpu, 0, 0);
1703        } else {
1704                if (auto_mode) {
1705                        if (status)
1706                                set_scaling_min_to_cpuinfo_max(cpu);
1707                        else
1708                                set_scaling_min_to_cpuinfo_min(cpu);
1709                }
1710        }
1711
1712        if (auto_mode && !status)
1713                isst_pm_qos_config(cpu, 0, 1);
1714
1715disp_result:
1716        if (status)
1717                isst_display_result(cpu, outf, "base-freq", "enable",
1718                                    ret);
1719        else
1720                isst_display_result(cpu, outf, "base-freq", "disable",
1721                                    ret);
1722}
1723
1724static void set_pbf_enable(int arg)
1725{
1726        int enable = arg;
1727
1728        if (cmd_help) {
1729                if (enable) {
1730                        fprintf(stderr,
1731                                "Enable Intel Speed Select Technology base frequency feature\n");
1732                        if (is_clx_n_platform()) {
1733                                fprintf(stderr,
1734                                        "\tOn this platform this command doesn't enable feature in the hardware.\n");
1735                                fprintf(stderr,
1736                                        "\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n");
1737                                exit(0);
1738
1739                        }
1740                        fprintf(stderr,
1741                                "\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n");
1742                } else {
1743
1744                        if (is_clx_n_platform()) {
1745                                fprintf(stderr,
1746                                        "\tOn this platform this command doesn't disable feature in the hardware.\n");
1747                                fprintf(stderr,
1748                                        "\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n");
1749                                exit(0);
1750                        }
1751                        fprintf(stderr,
1752                                "Disable Intel Speed Select Technology base frequency feature\n");
1753                        fprintf(stderr,
1754                                "\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
1755                }
1756                exit(0);
1757        }
1758
1759        isst_ctdp_display_information_start(outf);
1760        if (max_target_cpus)
1761                for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
1762                                                  NULL, &enable);
1763        else
1764                for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
1765                                               NULL, &enable);
1766        isst_ctdp_display_information_end(outf);
1767}
1768
1769static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2,
1770                                     void *arg3, void *arg4)
1771{
1772        struct isst_fact_info fact_info;
1773        int ret;
1774
1775        ret = isst_get_fact_info(cpu, tdp_level, fact_bucket, &fact_info);
1776        if (ret) {
1777                isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level);
1778                isst_ctdp_display_information_end(outf);
1779                exit(1);
1780        } else {
1781                isst_fact_display_information(cpu, outf, tdp_level, fact_bucket,
1782                                              fact_avx, &fact_info);
1783        }
1784}
1785
1786static void dump_fact_config(int arg)
1787{
1788        if (cmd_help) {
1789                fprintf(stderr,
1790                        "Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n");
1791                fprintf(stderr,
1792                        "\tArguments: -l|--level : Specify tdp level\n");
1793                fprintf(stderr,
1794                        "\tArguments: -b|--bucket : Bucket index to dump\n");
1795                fprintf(stderr,
1796                        "\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n");
1797                exit(0);
1798        }
1799
1800        if (tdp_level == 0xff) {
1801                isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0);
1802                exit(1);
1803        }
1804
1805        isst_ctdp_display_information_start(outf);
1806        if (max_target_cpus)
1807                for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
1808                                                  NULL, NULL, NULL, NULL);
1809        else
1810                for_each_online_package_in_set(dump_fact_config_for_cpu, NULL,
1811                                               NULL, NULL, NULL);
1812        isst_ctdp_display_information_end(outf);
1813}
1814
1815static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1816                             void *arg4)
1817{
1818        struct isst_pkg_ctdp_level_info ctdp_level;
1819        struct isst_pkg_ctdp pkg_dev;
1820        int ret;
1821        int status = *(int *)arg4;
1822
1823        ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1824        if (ret) {
1825                isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
1826                goto disp_results;
1827        }
1828
1829        ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
1830        if (ret) {
1831                isst_display_error_info_message(1, "Failed to get current level", 0, 0);
1832                goto disp_results;
1833        }
1834
1835        if (!ctdp_level.fact_support) {
1836                isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, pkg_dev.current_level);
1837                ret = -1;
1838                goto disp_results;
1839        }
1840
1841        if (status) {
1842                ret = isst_pm_qos_config(cpu, 1, 1);
1843                if (ret)
1844                        goto disp_results;
1845        }
1846
1847        ret = isst_set_pbf_fact_status(cpu, 0, status);
1848        if (ret) {
1849                debug_printf("isst_set_pbf_fact_status failed");
1850                if (auto_mode)
1851                        isst_pm_qos_config(cpu, 0, 0);
1852
1853                goto disp_results;
1854        }
1855
1856        /* Set TRL */
1857        if (status) {
1858                struct isst_pkg_ctdp pkg_dev;
1859
1860                ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1861                if (!ret)
1862                        ret = isst_set_trl(cpu, fact_trl);
1863                if (ret && auto_mode)
1864                        isst_pm_qos_config(cpu, 0, 0);
1865        } else {
1866                if (auto_mode)
1867                        isst_pm_qos_config(cpu, 0, 0);
1868        }
1869
1870disp_results:
1871        if (status) {
1872                isst_display_result(cpu, outf, "turbo-freq", "enable", ret);
1873                if (ret)
1874                        fact_enable_fail = ret;
1875        } else {
1876                /* Since we modified TRL during Fact enable, restore it */
1877                isst_set_trl_from_current_tdp(cpu, fact_trl);
1878                isst_display_result(cpu, outf, "turbo-freq", "disable", ret);
1879        }
1880}
1881
1882static void set_fact_enable(int arg)
1883{
1884        int i, ret, enable = arg;
1885
1886        if (cmd_help) {
1887                if (enable) {
1888                        fprintf(stderr,
1889                                "Enable Intel Speed Select Technology Turbo frequency feature\n");
1890                        fprintf(stderr,
1891                                "Optional: -t|--trl : Specify turbo ratio limit\n");
1892                        fprintf(stderr,
1893                                "\tOptional Arguments: -a|--auto : Designate specified target CPUs with");
1894                        fprintf(stderr,
1895                                "-C|--cpu option as as high priority using core-power feature\n");
1896                } else {
1897                        fprintf(stderr,
1898                                "Disable Intel Speed Select Technology turbo frequency feature\n");
1899                        fprintf(stderr,
1900                                "Optional: -t|--trl : Specify turbo ratio limit\n");
1901                        fprintf(stderr,
1902                                "\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
1903                }
1904                exit(0);
1905        }
1906
1907        isst_ctdp_display_information_start(outf);
1908        if (max_target_cpus)
1909                for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
1910                                                  NULL, &enable);
1911        else
1912                for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
1913                                               NULL, &enable);
1914        isst_ctdp_display_information_end(outf);
1915
1916        if (!fact_enable_fail && enable && auto_mode) {
1917                /*
1918                 * When we adjust CLOS param, we have to set for siblings also.
1919                 * So for the each user specified CPU, also add the sibling
1920                 * in the present_cpu_mask.
1921                 */
1922                for (i = 0; i < get_topo_max_cpus(); ++i) {
1923                        char buffer[128], sibling_list[128], *cpu_str;
1924                        int fd, len;
1925
1926                        if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
1927                                continue;
1928
1929                        snprintf(buffer, sizeof(buffer),
1930                                 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i);
1931
1932                        fd = open(buffer, O_RDONLY);
1933                        if (fd < 0)
1934                                continue;
1935
1936                        len = read(fd, sibling_list, sizeof(sibling_list));
1937                        close(fd);
1938
1939                        if (len < 0)
1940                                continue;
1941
1942                        cpu_str = strtok(sibling_list, ",");
1943                        while (cpu_str != NULL) {
1944                                int cpu;
1945
1946                                sscanf(cpu_str, "%d", &cpu);
1947                                CPU_SET_S(cpu, target_cpumask_size, target_cpumask);
1948                                cpu_str = strtok(NULL, ",");
1949                        }
1950                }
1951
1952                for (i = 0; i < get_topo_max_cpus(); ++i) {
1953                        int clos;
1954
1955                        if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
1956                                continue;
1957
1958                        ret = set_clos_param(i, 0, 0, 0, 0, 0xff);
1959                        if (ret)
1960                                goto error_disp;
1961
1962                        ret = set_clos_param(i, 1, 15, 15, 0, 0xff);
1963                        if (ret)
1964                                goto error_disp;
1965
1966                        ret = set_clos_param(i, 2, 15, 15, 0, 0xff);
1967                        if (ret)
1968                                goto error_disp;
1969
1970                        ret = set_clos_param(i, 3, 15, 15, 0, 0xff);
1971                        if (ret)
1972                                goto error_disp;
1973
1974                        if (CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
1975                                clos = 0;
1976                        else
1977                                clos = 3;
1978
1979                        debug_printf("Associate cpu: %d clos: %d\n", i, clos);
1980                        ret = isst_clos_associate(i, clos);
1981                        if (ret)
1982                                goto error_disp;
1983                }
1984                isst_display_result(-1, outf, "turbo-freq --auto", "enable", 0);
1985        }
1986
1987        return;
1988
1989error_disp:
1990        isst_display_result(i, outf, "turbo-freq --auto", "enable", ret);
1991
1992}
1993
1994static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3,
1995                                   void *arg4)
1996{
1997        int ret;
1998        int status = *(int *)arg4;
1999
2000        if (is_skx_based_platform())
2001                clos_priority_type = 1;
2002
2003        ret = isst_pm_qos_config(cpu, status, clos_priority_type);
2004        if (ret)
2005                isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0);
2006
2007        if (status)
2008                isst_display_result(cpu, outf, "core-power", "enable",
2009                                    ret);
2010        else
2011                isst_display_result(cpu, outf, "core-power", "disable",
2012                                    ret);
2013}
2014
2015static void set_clos_enable(int arg)
2016{
2017        int enable = arg;
2018
2019        if (cmd_help) {
2020                if (enable) {
2021                        fprintf(stderr,
2022                                "Enable core-power for a package/die\n");
2023                        if (!is_skx_based_platform()) {
2024                                fprintf(stderr,
2025                                        "\tClos Enable: Specify priority type with [--priority|-p]\n");
2026                                fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
2027                        }
2028                } else {
2029                        fprintf(stderr,
2030                                "Disable core-power: [No command arguments are required]\n");
2031                }
2032                exit(0);
2033        }
2034
2035        if (enable && cpufreq_sysfs_present()) {
2036                fprintf(stderr,
2037                        "cpufreq subsystem and core-power enable will interfere with each other!\n");
2038        }
2039
2040        isst_ctdp_display_information_start(outf);
2041        if (max_target_cpus)
2042                for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
2043                                                  NULL, NULL, &enable);
2044        else
2045                for_each_online_package_in_set(enable_clos_qos_config, NULL,
2046                                               NULL, NULL, &enable);
2047        isst_ctdp_display_information_end(outf);
2048}
2049
2050static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2,
2051                                     void *arg3, void *arg4)
2052{
2053        struct isst_clos_config clos_config;
2054        int ret;
2055
2056        ret = isst_pm_get_clos(cpu, current_clos, &clos_config);
2057        if (ret)
2058                isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
2059        else
2060                isst_clos_display_information(cpu, outf, current_clos,
2061                                              &clos_config);
2062}
2063
2064static void dump_clos_config(int arg)
2065{
2066        if (cmd_help) {
2067                fprintf(stderr,
2068                        "Print Intel Speed Select Technology core power configuration\n");
2069                fprintf(stderr,
2070                        "\tArguments: [-c | --clos]: Specify clos id\n");
2071                exit(0);
2072        }
2073        if (current_clos < 0 || current_clos > 3) {
2074                isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
2075                isst_ctdp_display_information_end(outf);
2076                exit(0);
2077        }
2078
2079        isst_ctdp_display_information_start(outf);
2080        if (max_target_cpus)
2081                for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
2082                                                  NULL, NULL, NULL, NULL);
2083        else
2084                for_each_online_package_in_set(dump_clos_config_for_cpu, NULL,
2085                                               NULL, NULL, NULL);
2086        isst_ctdp_display_information_end(outf);
2087}
2088
2089static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2090                                  void *arg4)
2091{
2092        int enable, ret, prio_type;
2093
2094        ret = isst_clos_get_clos_information(cpu, &enable, &prio_type);
2095        if (ret)
2096                isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0);
2097        else {
2098                int cp_state, cp_cap;
2099
2100                isst_read_pm_config(cpu, &cp_state, &cp_cap);
2101                isst_clos_display_clos_information(cpu, outf, enable, prio_type,
2102                                                   cp_state, cp_cap);
2103        }
2104}
2105
2106static void dump_clos_info(int arg)
2107{
2108        if (cmd_help) {
2109                fprintf(stderr,
2110                        "Print Intel Speed Select Technology core power information\n");
2111                fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n");
2112                exit(0);
2113        }
2114
2115        isst_ctdp_display_information_start(outf);
2116        if (max_target_cpus)
2117                for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
2118                                                  NULL, NULL, NULL);
2119        else
2120                for_each_online_package_in_set(get_clos_info_for_cpu, NULL,
2121                                               NULL, NULL, NULL);
2122        isst_ctdp_display_information_end(outf);
2123
2124}
2125
2126static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2127                                    void *arg4)
2128{
2129        struct isst_clos_config clos_config;
2130        int ret;
2131
2132        clos_config.pkg_id = get_physical_package_id(cpu);
2133        clos_config.die_id = get_physical_die_id(cpu);
2134
2135        clos_config.epp = clos_epp;
2136        clos_config.clos_prop_prio = clos_prop_prio;
2137        clos_config.clos_min = clos_min;
2138        clos_config.clos_max = clos_max;
2139        clos_config.clos_desired = clos_desired;
2140        ret = isst_set_clos(cpu, current_clos, &clos_config);
2141        if (ret)
2142                isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
2143        else
2144                isst_display_result(cpu, outf, "core-power", "config", ret);
2145}
2146
2147static void set_clos_config(int arg)
2148{
2149        if (cmd_help) {
2150                fprintf(stderr,
2151                        "Set core-power configuration for one of the four clos ids\n");
2152                fprintf(stderr,
2153                        "\tSpecify targeted clos id with [--clos|-c]\n");
2154                if (!is_skx_based_platform()) {
2155                        fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
2156                        fprintf(stderr,
2157                                "\tSpecify clos Proportional Priority [--weight|-w]\n");
2158                }
2159                fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n");
2160                fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n");
2161                exit(0);
2162        }
2163
2164        if (current_clos < 0 || current_clos > 3) {
2165                isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
2166                exit(0);
2167        }
2168        if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) {
2169                fprintf(stderr, "clos epp is not specified or invalid, default: 0\n");
2170                clos_epp = 0;
2171        }
2172        if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) {
2173                fprintf(stderr,
2174                        "clos frequency weight is not specified or invalid, default: 0\n");
2175                clos_prop_prio = 0;
2176        }
2177        if (clos_min < 0) {
2178                fprintf(stderr, "clos min is not specified, default: 0\n");
2179                clos_min = 0;
2180        }
2181        if (clos_max < 0) {
2182                fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n");
2183                clos_max = 0xff;
2184        }
2185        if (clos_desired) {
2186                fprintf(stderr, "clos desired is not supported on this platform\n");
2187                clos_desired = 0x00;
2188        }
2189
2190        isst_ctdp_display_information_start(outf);
2191        if (max_target_cpus)
2192                for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
2193                                                  NULL, NULL, NULL);
2194        else
2195                for_each_online_package_in_set(set_clos_config_for_cpu, NULL,
2196                                               NULL, NULL, NULL);
2197        isst_ctdp_display_information_end(outf);
2198}
2199
2200static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2201                                   void *arg4)
2202{
2203        int ret;
2204
2205        ret = isst_clos_associate(cpu, current_clos);
2206        if (ret)
2207                debug_printf("isst_clos_associate failed");
2208        else
2209                isst_display_result(cpu, outf, "core-power", "assoc", ret);
2210}
2211
2212static void set_clos_assoc(int arg)
2213{
2214        if (cmd_help) {
2215                fprintf(stderr, "Associate a clos id to a CPU\n");
2216                fprintf(stderr,
2217                        "\tSpecify targeted clos id with [--clos|-c]\n");
2218                fprintf(stderr,
2219                        "\tFor example to associate clos 1 to CPU 0: issue\n");
2220                fprintf(stderr,
2221                        "\tintel-speed-select --cpu 0 core-power assoc --clos 1\n");
2222                exit(0);
2223        }
2224
2225        if (current_clos < 0 || current_clos > 3) {
2226                isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
2227                exit(0);
2228        }
2229        if (max_target_cpus)
2230                for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
2231                                                  NULL, NULL, NULL);
2232        else {
2233                isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
2234        }
2235}
2236
2237static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2238                                   void *arg4)
2239{
2240        int clos, ret;
2241
2242        ret = isst_clos_get_assoc_status(cpu, &clos);
2243        if (ret)
2244                isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0);
2245        else
2246                isst_clos_display_assoc_information(cpu, outf, clos);
2247}
2248
2249static void get_clos_assoc(int arg)
2250{
2251        if (cmd_help) {
2252                fprintf(stderr, "Get associate clos id to a CPU\n");
2253                fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
2254                exit(0);
2255        }
2256
2257        if (!max_target_cpus) {
2258                isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
2259                exit(0);
2260        }
2261
2262        isst_ctdp_display_information_start(outf);
2263        for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL,
2264                                          NULL, NULL, NULL);
2265        isst_ctdp_display_information_end(outf);
2266}
2267
2268static struct process_cmd_struct clx_n_cmds[] = {
2269        { "perf-profile", "info", dump_isst_config, 0 },
2270        { "base-freq", "info", dump_pbf_config, 0 },
2271        { "base-freq", "enable", set_pbf_enable, 1 },
2272        { "base-freq", "disable", set_pbf_enable, 0 },
2273        { NULL, NULL, NULL, 0 }
2274};
2275
2276static struct process_cmd_struct isst_cmds[] = {
2277        { "perf-profile", "get-lock-status", get_tdp_locked, 0 },
2278        { "perf-profile", "get-config-levels", get_tdp_levels, 0 },
2279        { "perf-profile", "get-config-version", get_tdp_version, 0 },
2280        { "perf-profile", "get-config-enabled", get_tdp_enabled, 0 },
2281        { "perf-profile", "get-config-current-level", get_tdp_current_level,
2282         0 },
2283        { "perf-profile", "set-config-level", set_tdp_level, 0 },
2284        { "perf-profile", "info", dump_isst_config, 0 },
2285        { "base-freq", "info", dump_pbf_config, 0 },
2286        { "base-freq", "enable", set_pbf_enable, 1 },
2287        { "base-freq", "disable", set_pbf_enable, 0 },
2288        { "turbo-freq", "info", dump_fact_config, 0 },
2289        { "turbo-freq", "enable", set_fact_enable, 1 },
2290        { "turbo-freq", "disable", set_fact_enable, 0 },
2291        { "core-power", "info", dump_clos_info, 0 },
2292        { "core-power", "enable", set_clos_enable, 1 },
2293        { "core-power", "disable", set_clos_enable, 0 },
2294        { "core-power", "config", set_clos_config, 0 },
2295        { "core-power", "get-config", dump_clos_config, 0 },
2296        { "core-power", "assoc", set_clos_assoc, 0 },
2297        { "core-power", "get-assoc", get_clos_assoc, 0 },
2298        { NULL, NULL, NULL }
2299};
2300
2301/*
2302 * parse cpuset with following syntax
2303 * 1,2,4..6,8-10 and set bits in cpu_subset
2304 */
2305void parse_cpu_command(char *optarg)
2306{
2307        unsigned int start, end;
2308        char *next;
2309
2310        next = optarg;
2311
2312        while (next && *next) {
2313                if (*next == '-') /* no negative cpu numbers */
2314                        goto error;
2315
2316                start = strtoul(next, &next, 10);
2317
2318                if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
2319                        target_cpus[max_target_cpus++] = start;
2320
2321                if (*next == '\0')
2322                        break;
2323
2324                if (*next == ',') {
2325                        next += 1;
2326                        continue;
2327                }
2328
2329                if (*next == '-') {
2330                        next += 1; /* start range */
2331                } else if (*next == '.') {
2332                        next += 1;
2333                        if (*next == '.')
2334                                next += 1; /* start range */
2335                        else
2336                                goto error;
2337                }
2338
2339                end = strtoul(next, &next, 10);
2340                if (end <= start)
2341                        goto error;
2342
2343                while (++start <= end) {
2344                        if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
2345                                target_cpus[max_target_cpus++] = start;
2346                }
2347
2348                if (*next == ',')
2349                        next += 1;
2350                else if (*next != '\0')
2351                        goto error;
2352        }
2353
2354#ifdef DEBUG
2355        {
2356                int i;
2357
2358                for (i = 0; i < max_target_cpus; ++i)
2359                        printf("cpu [%d] in arg\n", target_cpus[i]);
2360        }
2361#endif
2362        return;
2363
2364error:
2365        fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
2366        exit(-1);
2367}
2368
2369static void parse_cmd_args(int argc, int start, char **argv)
2370{
2371        int opt;
2372        int option_index;
2373
2374        static struct option long_options[] = {
2375                { "bucket", required_argument, 0, 'b' },
2376                { "level", required_argument, 0, 'l' },
2377                { "online", required_argument, 0, 'o' },
2378                { "trl-type", required_argument, 0, 'r' },
2379                { "trl", required_argument, 0, 't' },
2380                { "help", no_argument, 0, 'h' },
2381                { "clos", required_argument, 0, 'c' },
2382                { "desired", required_argument, 0, 'd' },
2383                { "epp", required_argument, 0, 'e' },
2384                { "min", required_argument, 0, 'n' },
2385                { "max", required_argument, 0, 'm' },
2386                { "priority", required_argument, 0, 'p' },
2387                { "weight", required_argument, 0, 'w' },
2388                { "auto", no_argument, 0, 'a' },
2389                { 0, 0, 0, 0 }
2390        };
2391
2392        option_index = start;
2393
2394        optind = start + 1;
2395        while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa",
2396                                  long_options, &option_index)) != -1) {
2397                switch (opt) {
2398                case 'a':
2399                        auto_mode = 1;
2400                        break;
2401                case 'b':
2402                        fact_bucket = atoi(optarg);
2403                        break;
2404                case 'h':
2405                        cmd_help = 1;
2406                        break;
2407                case 'l':
2408                        tdp_level = atoi(optarg);
2409                        break;
2410                case 'o':
2411                        force_online_offline = 1;
2412                        break;
2413                case 't':
2414                        sscanf(optarg, "0x%llx", &fact_trl);
2415                        break;
2416                case 'r':
2417                        if (!strncmp(optarg, "sse", 3)) {
2418                                fact_avx = 0x01;
2419                        } else if (!strncmp(optarg, "avx2", 4)) {
2420                                fact_avx = 0x02;
2421                        } else if (!strncmp(optarg, "avx512", 6)) {
2422                                fact_avx = 0x04;
2423                        } else {
2424                                fprintf(outf, "Invalid sse,avx options\n");
2425                                exit(1);
2426                        }
2427                        break;
2428                /* CLOS related */
2429                case 'c':
2430                        current_clos = atoi(optarg);
2431                        break;
2432                case 'd':
2433                        clos_desired = atoi(optarg);
2434                        clos_desired /= DISP_FREQ_MULTIPLIER;
2435                        break;
2436                case 'e':
2437                        clos_epp = atoi(optarg);
2438                        if (is_skx_based_platform()) {
2439                                isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0);
2440                                exit(0);
2441                        }
2442                        break;
2443                case 'n':
2444                        clos_min = atoi(optarg);
2445                        clos_min /= DISP_FREQ_MULTIPLIER;
2446                        break;
2447                case 'm':
2448                        clos_max = atoi(optarg);
2449                        clos_max /= DISP_FREQ_MULTIPLIER;
2450                        break;
2451                case 'p':
2452                        clos_priority_type = atoi(optarg);
2453                        if (is_skx_based_platform() && !clos_priority_type) {
2454                                isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0);
2455                                exit(0);
2456                        }
2457                        break;
2458                case 'w':
2459                        clos_prop_prio = atoi(optarg);
2460                        if (is_skx_based_platform()) {
2461                                isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0);
2462                                exit(0);
2463                        }
2464                        break;
2465                default:
2466                        printf("Unknown option: ignore\n");
2467                }
2468        }
2469
2470        if (argv[optind])
2471                printf("Garbage at the end of command: ignore\n");
2472}
2473
2474static void isst_help(void)
2475{
2476        printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\
2477                performance profiles per system via static and/or dynamic\n\
2478                adjustment of core count, workload, Tjmax, and\n\
2479                TDP, etc.\n");
2480        printf("\nCommands : For feature=perf-profile\n");
2481        printf("\tinfo\n");
2482
2483        if (!is_clx_n_platform()) {
2484                printf("\tget-lock-status\n");
2485                printf("\tget-config-levels\n");
2486                printf("\tget-config-version\n");
2487                printf("\tget-config-enabled\n");
2488                printf("\tget-config-current-level\n");
2489                printf("\tset-config-level\n");
2490        }
2491}
2492
2493static void pbf_help(void)
2494{
2495        printf("base-freq:\tEnables users to increase guaranteed base frequency\n\
2496                on certain cores (high priority cores) in exchange for lower\n\
2497                base frequency on remaining cores (low priority cores).\n");
2498        printf("\tcommand : info\n");
2499        printf("\tcommand : enable\n");
2500        printf("\tcommand : disable\n");
2501}
2502
2503static void fact_help(void)
2504{
2505        printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\
2506                limits to cores based on priority.\n");
2507        printf("\nCommand: For feature=turbo-freq\n");
2508        printf("\tcommand : info\n");
2509        printf("\tcommand : enable\n");
2510        printf("\tcommand : disable\n");
2511}
2512
2513static void core_power_help(void)
2514{
2515        printf("core-power:\tInterface that allows user to define per core/tile\n\
2516                priority.\n");
2517        printf("\nCommands : For feature=core-power\n");
2518        printf("\tinfo\n");
2519        printf("\tenable\n");
2520        printf("\tdisable\n");
2521        printf("\tconfig\n");
2522        printf("\tget-config\n");
2523        printf("\tassoc\n");
2524        printf("\tget-assoc\n");
2525}
2526
2527struct process_cmd_help_struct {
2528        char *feature;
2529        void (*process_fn)(void);
2530};
2531
2532static struct process_cmd_help_struct isst_help_cmds[] = {
2533        { "perf-profile", isst_help },
2534        { "base-freq", pbf_help },
2535        { "turbo-freq", fact_help },
2536        { "core-power", core_power_help },
2537        { NULL, NULL }
2538};
2539
2540static struct process_cmd_help_struct clx_n_help_cmds[] = {
2541        { "perf-profile", isst_help },
2542        { "base-freq", pbf_help },
2543        { NULL, NULL }
2544};
2545
2546void process_command(int argc, char **argv,
2547                     struct process_cmd_help_struct *help_cmds,
2548                     struct process_cmd_struct *cmds)
2549{
2550        int i = 0, matched = 0;
2551        char *feature = argv[optind];
2552        char *cmd = argv[optind + 1];
2553
2554        if (!feature || !cmd)
2555                return;
2556
2557        debug_printf("feature name [%s] command [%s]\n", feature, cmd);
2558        if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
2559                while (help_cmds[i].feature) {
2560                        if (!strcmp(help_cmds[i].feature, feature)) {
2561                                help_cmds[i].process_fn();
2562                                exit(0);
2563                        }
2564                        ++i;
2565                }
2566        }
2567
2568        if (!is_clx_n_platform())
2569                create_cpu_map();
2570
2571        i = 0;
2572        while (cmds[i].feature) {
2573                if (!strcmp(cmds[i].feature, feature) &&
2574                    !strcmp(cmds[i].command, cmd)) {
2575                        parse_cmd_args(argc, optind + 1, argv);
2576                        cmds[i].process_fn(cmds[i].arg);
2577                        matched = 1;
2578                        break;
2579                }
2580                ++i;
2581        }
2582
2583        if (!matched)
2584                fprintf(stderr, "Invalid command\n");
2585}
2586
2587static void usage(void)
2588{
2589        if (is_clx_n_platform()) {
2590                fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n");
2591                fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n");
2592        }
2593
2594        printf("\nUsage:\n");
2595        printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
2596        printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n");
2597        if (is_clx_n_platform())
2598                printf("\nFEATURE : [perf-profile|base-freq]\n");
2599        else
2600                printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
2601        printf("\nFor help on each feature, use -h|--help\n");
2602        printf("\tFor example:  intel-speed-select perf-profile -h\n");
2603
2604        printf("\nFor additional help on each command for a feature, use --h|--help\n");
2605        printf("\tFor example:  intel-speed-select perf-profile get-lock-status -h\n");
2606        printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n");
2607
2608        printf("\nOPTIONS\n");
2609        printf("\t[-c|--cpu] : logical cpu number\n");
2610        printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n");
2611        printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n");
2612        printf("\t[-d|--debug] : Debug mode\n");
2613        printf("\t[-f|--format] : output format [json|text]. Default: text\n");
2614        printf("\t[-h|--help] : Print help\n");
2615        printf("\t[-i|--info] : Print platform information\n");
2616        printf("\t[-o|--out] : Output file\n");
2617        printf("\t\t\tDefault : stderr\n");
2618        printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n");
2619        printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n");
2620        printf("\t[-v|--version] : Print version\n");
2621
2622        printf("\nResult format\n");
2623        printf("\tResult display uses a common format for each command:\n");
2624        printf("\tResults are formatted in text/JSON with\n");
2625        printf("\t\tPackage, Die, CPU, and command specific results.\n");
2626
2627        printf("\nExamples\n");
2628        printf("\tTo get platform information:\n");
2629        printf("\t\tintel-speed-select --info\n");
2630        printf("\tTo get full perf-profile information dump:\n");
2631        printf("\t\tintel-speed-select perf-profile info\n");
2632        printf("\tTo get full base-freq information dump:\n");
2633        printf("\t\tintel-speed-select base-freq info -l 0\n");
2634        if (!is_clx_n_platform()) {
2635                printf("\tTo get full turbo-freq information dump:\n");
2636                printf("\t\tintel-speed-select turbo-freq info -l 0\n");
2637        }
2638        exit(1);
2639}
2640
2641static void print_version(void)
2642{
2643        fprintf(outf, "Version %s\n", version_str);
2644        fprintf(outf, "Build date %s time %s\n", __DATE__, __TIME__);
2645        exit(0);
2646}
2647
2648static void cmdline(int argc, char **argv)
2649{
2650        const char *pathname = "/dev/isst_interface";
2651        char *ptr;
2652        FILE *fp;
2653        int opt;
2654        int option_index = 0;
2655        int ret;
2656
2657        static struct option long_options[] = {
2658                { "cpu", required_argument, 0, 'c' },
2659                { "debug", no_argument, 0, 'd' },
2660                { "format", required_argument, 0, 'f' },
2661                { "help", no_argument, 0, 'h' },
2662                { "info", no_argument, 0, 'i' },
2663                { "pause", required_argument, 0, 'p' },
2664                { "out", required_argument, 0, 'o' },
2665                { "retry", required_argument, 0, 'r' },
2666                { "version", no_argument, 0, 'v' },
2667                { 0, 0, 0, 0 }
2668        };
2669
2670        if (geteuid() != 0) {
2671                fprintf(stderr, "Must run as root\n");
2672                exit(0);
2673        }
2674
2675        ret = update_cpu_model();
2676        if (ret)
2677                err(-1, "Invalid CPU model (%d)\n", cpu_model);
2678        printf("Intel(R) Speed Select Technology\n");
2679        printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
2680
2681        if (!is_clx_n_platform()) {
2682                fp = fopen(pathname, "rb");
2683                if (!fp) {
2684                        fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n");
2685                        fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n");
2686                        fprintf(stderr, "If the config is included then this is not a supported platform.\n");
2687                        exit(0);
2688                }
2689                fclose(fp);
2690        }
2691
2692        progname = argv[0];
2693        while ((opt = getopt_long_only(argc, argv, "+c:df:hio:v", long_options,
2694                                       &option_index)) != -1) {
2695                switch (opt) {
2696                case 'c':
2697                        parse_cpu_command(optarg);
2698                        break;
2699                case 'd':
2700                        debug_flag = 1;
2701                        printf("Debug Mode ON\n");
2702                        break;
2703                case 'f':
2704                        if (!strncmp(optarg, "json", 4))
2705                                out_format_json = 1;
2706                        break;
2707                case 'h':
2708                        usage();
2709                        break;
2710                case 'i':
2711                        isst_print_platform_information();
2712                        break;
2713                case 'o':
2714                        if (outf)
2715                                fclose(outf);
2716                        outf = fopen_or_exit(optarg, "w");
2717                        break;
2718                case 'p':
2719                        ret = strtol(optarg, &ptr, 10);
2720                        if (!ret)
2721                                fprintf(stderr, "Invalid pause interval, ignore\n");
2722                        else
2723                                mbox_delay = ret;
2724                        break;
2725                case 'r':
2726                        ret = strtol(optarg, &ptr, 10);
2727                        if (!ret)
2728                                fprintf(stderr, "Invalid retry count, ignore\n");
2729                        else
2730                                mbox_retries = ret;
2731                        break;
2732                case 'v':
2733                        print_version();
2734                        break;
2735                default:
2736                        usage();
2737                }
2738        }
2739
2740        if (optind > (argc - 2)) {
2741                usage();
2742                exit(0);
2743        }
2744        set_max_cpu_num();
2745        store_cpu_topology();
2746        set_cpu_present_cpu_mask();
2747        set_cpu_target_cpu_mask();
2748
2749        if (!is_clx_n_platform()) {
2750                ret = isst_fill_platform_info();
2751                if (ret)
2752                        goto out;
2753                process_command(argc, argv, isst_help_cmds, isst_cmds);
2754        } else {
2755                process_command(argc, argv, clx_n_help_cmds, clx_n_cmds);
2756        }
2757out:
2758        free_cpu_set(present_cpumask);
2759        free_cpu_set(target_cpumask);
2760}
2761
2762int main(int argc, char **argv)
2763{
2764        outf = stderr;
2765        cmdline(argc, argv);
2766        return 0;
2767}
2768