Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  hfi-events.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Intel Speed Select -- Read HFI events for OOB
 * Copyright (c) 2022 Intel Corporation.
 */


/*
 * This file incorporates work covered by the following copyright and
 * permission notice:

 * WPA Supplicant - driver interaction with Linux nl80211/cfg80211
 * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Alternatively, this software may be distributed under the terms of
 * BSD license.
 *
 * Requires
 * libnl-genl-3-dev
 *
 * For Fedora/CenOS
 * dnf install libnl3-devel
 * For Ubuntu
 * apt install libnl-3-dev libnl-genl-3-dev
 */


#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>

#include <linux/thermal.h>
#include "isst.h"

struct hfi_event_data {
 struct nl_sock *nl_handle;
 struct nl_cb *nl_cb;
};

struct hfi_event_data drv;

static int ack_handler(struct nl_msg *msg, void *arg)
{
 int *err = arg;
 *err = 0;
 return NL_STOP;
}

static int finish_handler(struct nl_msg *msg, void *arg)
{
 int *ret = arg;
 *ret = 0;
 return NL_SKIP;
}

static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
    void *arg)
{
 int *ret = arg;
 *ret = err->error;
 return NL_SKIP;
}

static int seq_check_handler(struct nl_msg *msg, void *arg)
{
 return NL_OK;
}

static int send_and_recv_msgs(struct hfi_event_data *drv,
         struct nl_msg *msg,
         int (*valid_handler)(struct nl_msg *, void *),
         void *valid_data)
{
 struct nl_cb *cb;
 int err = -ENOMEM;

 cb = nl_cb_clone(drv->nl_cb);
 if (!cb)
  goto out;

 err = nl_send_auto_complete(drv->nl_handle, msg);
 if (err < 0)
  goto out;

 err = 1;

 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);

 if (valid_handler)
  nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
     valid_handler, valid_data);

 while (err > 0)
  nl_recvmsgs(drv->nl_handle, cb);
 out:
 nl_cb_put(cb);
 nlmsg_free(msg);
 return err;
}

struct family_data {
 const char *group;
 int id;
};

static int family_handler(struct nl_msg *msg, void *arg)
{
 struct family_data *res = arg;
 struct nlattr *tb[CTRL_ATTR_MAX + 1];
 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
 struct nlattr *mcgrp;
 int i;

 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    genlmsg_attrlen(gnlh, 0), NULL);
 if (!tb[CTRL_ATTR_MCAST_GROUPS])
  return NL_SKIP;

 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
  struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
  nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
     nla_len(mcgrp), NULL);
  if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
      !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
      strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
    res->group,
    nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
   continue;
  res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
  break;
 }

 return 0;
}

static int nl_get_multicast_id(struct hfi_event_data *drv,
          const char *family, const char *group)
{
 struct nl_msg *msg;
 int ret = -1;
 struct family_data res = { group, -ENOENT };

 msg = nlmsg_alloc();
 if (!msg)
  return -ENOMEM;
 genlmsg_put(msg, 0, 0, genl_ctrl_resolve(drv->nl_handle, "nlctrl"),
      0, 0, CTRL_CMD_GETFAMILY, 0);
 NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);

 ret = send_and_recv_msgs(drv, msg, family_handler, &res);
 msg = NULL;
 if (ret == 0)
  ret = res.id;

nla_put_failure:
 nlmsg_free(msg);
 return ret;
}

struct perf_cap {
 int cpu;
 int perf;
 int eff;
};

static void process_hfi_event(struct perf_cap *perf_cap)
{
 struct isst_id id;

 set_isst_id(&id, perf_cap->cpu);
 process_level_change(&id);
}

static int handle_event(struct nl_msg *n, void *arg)
{
 struct nlmsghdr *nlh = nlmsg_hdr(n);
 struct genlmsghdr *genlhdr = genlmsg_hdr(nlh);
 struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
 int ret;
 struct perf_cap perf_cap = {0};

 ret = genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);

 debug_printf("Received event %d parse_rer:%d\n", genlhdr->cmd, ret);
 if (genlhdr->cmd == THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE) {
  struct nlattr *cap;
  int j, index = 0;

  debug_printf("THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE\n");
  nla_for_each_nested(cap, attrs[THERMAL_GENL_ATTR_CPU_CAPABILITY], j) {
   switch (index) {
   case 0:
    perf_cap.cpu = nla_get_u32(cap);
    break;
   case 1:
    perf_cap.perf = nla_get_u32(cap);
    break;
   case 2:
    perf_cap.eff = nla_get_u32(cap);
    break;
   default:
    break;
   }
   ++index;
   if (index == 3) {
    index = 0;
    process_hfi_event(&perf_cap);
   }
  }
 }

 return 0;
}

static int _hfi_exit;

static int check_hf_suport(void)
{
 unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;

 __cpuid(6, eax, ebx, ecx, edx);
 if (eax & BIT(19))
  return 1;

 return 0;
}

int hfi_main(void)
{
 struct nl_sock *sock;
 struct nl_cb *cb;
 int err = 0;
 int mcast_id;

 if (!check_hf_suport()) {
  fprintf(stderr, "CPU Doesn't support HFI\n");
  return -1;
 }

 sock = nl_socket_alloc();
 if (!sock) {
  fprintf(stderr, "nl_socket_alloc failed\n");
  return -1;
 }

 if (genl_connect(sock)) {
  fprintf(stderr, "genl_connect(sk_event) failed\n");
  goto free_sock;
 }

 drv.nl_handle = sock;
 drv.nl_cb = cb = nl_cb_alloc(NL_CB_DEFAULT);
 if (drv.nl_cb == NULL) {
  printf("Failed to allocate netlink callbacks");
  goto free_sock;
 }

 mcast_id = nl_get_multicast_id(&drv, THERMAL_GENL_FAMILY_NAME,
       THERMAL_GENL_EVENT_GROUP_NAME);
 if (mcast_id < 0) {
  fprintf(stderr, "nl_get_multicast_id failed\n");
  goto free_sock;
 }

 if (nl_socket_add_membership(sock, mcast_id)) {
  fprintf(stderr, "nl_socket_add_membership failed");
  goto free_sock;
 }

 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, seq_check_handler, 0);
 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handle_event, NULL);

 debug_printf("hfi is initialized\n");

 while (!_hfi_exit && !err) {
  err = nl_recvmsgs(sock, cb);
  debug_printf("nl_recv_message err:%d\n", err);
 }

 return 0;

 /* Netlink library doesn't have calls to dealloc cb or disconnect */
free_sock:
 nl_socket_free(sock);

 return -1;
}

void hfi_exit(void)
{
 _hfi_exit = 1;
}

Messung V0.5
C=92 H=91 G=91

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge