Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/platform/x86/intel/speed_select_if/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  isst_if_mmio.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Intel Speed Select Interface: MMIO Interface
 * Copyright (c) 2019, Intel Corporation.
 * All rights reserved.
 *
 * Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
 */


#include <linux/module.h>
#include <linux/pci.h>
#include <linux/sched/signal.h>
#include <linux/uaccess.h>
#include <uapi/linux/isst_if.h>

#include "isst_if_common.h"

struct isst_mmio_range {
 int beg;
 int end;
 int size;
};

static struct isst_mmio_range mmio_range_devid_0[] = {
 {0x04, 0x14, 0x18},
 {0x20, 0xD0, 0xD4},
};

static struct isst_mmio_range mmio_range_devid_1[] = {
 {0x04, 0x14, 0x18},
 {0x20, 0x11C, 0x120},
};

struct isst_if_device {
 void __iomem *punit_mmio;
 u32 range_0[5];
 u32 range_1[64];
 struct isst_mmio_range *mmio_range;
 struct mutex mutex;
};

static long isst_if_mmio_rd_wr(u8 *cmd_ptr, int *write_only, int resume)
{
 struct isst_if_device *punit_dev;
 struct isst_if_io_reg *io_reg;
 struct pci_dev *pdev;

 io_reg = (struct isst_if_io_reg *)cmd_ptr;

 if (io_reg->reg % 4)
  return -EINVAL;

 if (io_reg->read_write && !capable(CAP_SYS_ADMIN))
  return -EPERM;

 pdev = isst_if_get_pci_dev(io_reg->logical_cpu, 0, 0, 1);
 if (!pdev)
  return -EINVAL;

 punit_dev = pci_get_drvdata(pdev);
 if (!punit_dev)
  return -EINVAL;

 if (io_reg->reg < punit_dev->mmio_range[0].beg ||
     io_reg->reg > punit_dev->mmio_range[1].end)
  return -EINVAL;

 /*
 * Ensure that operation is complete on a PCI device to avoid read
 * write race by using per PCI device mutex.
 */

 mutex_lock(&punit_dev->mutex);
 if (io_reg->read_write) {
  writel(io_reg->value, punit_dev->punit_mmio+io_reg->reg);
  *write_only = 1;
 } else {
  io_reg->value = readl(punit_dev->punit_mmio+io_reg->reg);
  *write_only = 0;
 }
 mutex_unlock(&punit_dev->mutex);

 return 0;
}

static const struct pci_device_id isst_if_ids[] = {
 { PCI_DEVICE_DATA(INTEL, RAPL_PRIO_DEVID_0, &mmio_range_devid_0)},
 { PCI_DEVICE_DATA(INTEL, RAPL_PRIO_DEVID_1, &mmio_range_devid_1)},
 { 0 },
};
MODULE_DEVICE_TABLE(pci, isst_if_ids);

static int isst_if_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
 struct isst_if_device *punit_dev;
 struct isst_if_cmd_cb cb;
 u32 mmio_base, pcu_base;
 struct resource r;
 u64 base_addr;
 int ret;

 punit_dev = devm_kzalloc(&pdev->dev, sizeof(*punit_dev), GFP_KERNEL);
 if (!punit_dev)
  return -ENOMEM;

 ret = pcim_enable_device(pdev);
 if (ret)
  return ret;

 ret = pci_read_config_dword(pdev, 0xD0, &mmio_base);
 if (ret)
  return ret;

 ret = pci_read_config_dword(pdev, 0xFC, &pcu_base);
 if (ret)
  return ret;

 pcu_base &= GENMASK(10, 0);
 base_addr = (u64)mmio_base << 23 | (u64) pcu_base << 12;

 punit_dev->mmio_range = (struct isst_mmio_range *) ent->driver_data;

 r = DEFINE_RES_MEM(base_addr, punit_dev->mmio_range[1].size);
 punit_dev->punit_mmio = devm_ioremap_resource(&pdev->dev, &r);
 if (IS_ERR(punit_dev->punit_mmio))
  return PTR_ERR(punit_dev->punit_mmio);

 mutex_init(&punit_dev->mutex);
 pci_set_drvdata(pdev, punit_dev);

 memset(&cb, 0, sizeof(cb));
 cb.cmd_size = sizeof(struct isst_if_io_reg);
 cb.offset = offsetof(struct isst_if_io_regs, io_reg);
 cb.cmd_callback = isst_if_mmio_rd_wr;
 cb.owner = THIS_MODULE;
 ret = isst_if_cdev_register(ISST_IF_DEV_MMIO, &cb);
 if (ret)
  mutex_destroy(&punit_dev->mutex);

 return ret;
}

static void isst_if_remove(struct pci_dev *pdev)
{
 struct isst_if_device *punit_dev;

 punit_dev = pci_get_drvdata(pdev);
 isst_if_cdev_unregister(ISST_IF_DEV_MMIO);
 mutex_destroy(&punit_dev->mutex);
}

static int __maybe_unused isst_if_suspend(struct device *device)
{
 struct isst_if_device *punit_dev = dev_get_drvdata(device);
 int i;

 for (i = 0; i < ARRAY_SIZE(punit_dev->range_0); ++i)
  punit_dev->range_0[i] = readl(punit_dev->punit_mmio +
      punit_dev->mmio_range[0].beg + 4 * i);
 for (i = 0; i < ARRAY_SIZE(punit_dev->range_1); ++i) {
  u32 addr;

  addr = punit_dev->mmio_range[1].beg + 4 * i;
  if (addr > punit_dev->mmio_range[1].end)
   break;
  punit_dev->range_1[i] = readl(punit_dev->punit_mmio + addr);
 }

 return 0;
}

static int __maybe_unused isst_if_resume(struct device *device)
{
 struct isst_if_device *punit_dev = dev_get_drvdata(device);
 int i;

 for (i = 0; i < ARRAY_SIZE(punit_dev->range_0); ++i)
  writel(punit_dev->range_0[i], punit_dev->punit_mmio +
      punit_dev->mmio_range[0].beg + 4 * i);
 for (i = 0; i < ARRAY_SIZE(punit_dev->range_1); ++i) {
  u32 addr;

  addr = punit_dev->mmio_range[1].beg + 4 * i;
  if (addr > punit_dev->mmio_range[1].end)
   break;

  writel(punit_dev->range_1[i], punit_dev->punit_mmio + addr);
 }

 return 0;
}

static SIMPLE_DEV_PM_OPS(isst_if_pm_ops, isst_if_suspend, isst_if_resume);

static struct pci_driver isst_if_pci_driver = {
 .name   = "isst_if_pci",
 .id_table  = isst_if_ids,
 .probe   = isst_if_probe,
 .remove   = isst_if_remove,
 .driver.pm  = &isst_if_pm_ops,
};

module_pci_driver(isst_if_pci_driver);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel speed select interface mmio driver");

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.11 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.