cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ipmi_si_pci.c (3598B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * ipmi_si_pci.c
      4 *
      5 * Handling for IPMI devices on the PCI bus.
      6 */
      7
      8#define pr_fmt(fmt) "ipmi_pci: " fmt
      9
     10#include <linux/module.h>
     11#include <linux/pci.h>
     12#include "ipmi_si.h"
     13
     14static bool pci_registered;
     15
     16static bool si_trypci = true;
     17
     18module_param_named(trypci, si_trypci, bool, 0);
     19MODULE_PARM_DESC(trypci,
     20		 "Setting this to zero will disable the default scan of the interfaces identified via pci");
     21
     22#define PCI_DEVICE_ID_HP_MMC 0x121A
     23
     24static int ipmi_pci_probe_regspacing(struct si_sm_io *io)
     25{
     26	if (io->si_type == SI_KCS) {
     27		unsigned char	status;
     28		int		regspacing;
     29
     30		io->regsize = DEFAULT_REGSIZE;
     31		io->regshift = 0;
     32
     33		/* detect 1, 4, 16byte spacing */
     34		for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) {
     35			io->regspacing = regspacing;
     36			if (io->io_setup(io)) {
     37				dev_err(io->dev, "Could not setup I/O space\n");
     38				return DEFAULT_REGSPACING;
     39			}
     40			/* write invalid cmd */
     41			io->outputb(io, 1, 0x10);
     42			/* read status back */
     43			status = io->inputb(io, 1);
     44			io->io_cleanup(io);
     45			if (status)
     46				return regspacing;
     47			regspacing *= 4;
     48		}
     49	}
     50	return DEFAULT_REGSPACING;
     51}
     52
     53static struct pci_device_id ipmi_pci_blacklist[] = {
     54	/*
     55	 * This is a "Virtual IPMI device", whatever that is.  It appears
     56	 * as a KCS device by the class, but it is not one.
     57	 */
     58	{ PCI_VDEVICE(REALTEK, 0x816c) },
     59	{ 0, }
     60};
     61
     62static int ipmi_pci_probe(struct pci_dev *pdev,
     63				    const struct pci_device_id *ent)
     64{
     65	int rv;
     66	struct si_sm_io io;
     67
     68	if (pci_match_id(ipmi_pci_blacklist, pdev))
     69		return -ENODEV;
     70
     71	memset(&io, 0, sizeof(io));
     72	io.addr_source = SI_PCI;
     73	dev_info(&pdev->dev, "probing via PCI");
     74
     75	switch (pdev->class) {
     76	case PCI_CLASS_SERIAL_IPMI_SMIC:
     77		io.si_type = SI_SMIC;
     78		break;
     79
     80	case PCI_CLASS_SERIAL_IPMI_KCS:
     81		io.si_type = SI_KCS;
     82		break;
     83
     84	case PCI_CLASS_SERIAL_IPMI_BT:
     85		io.si_type = SI_BT;
     86		break;
     87
     88	default:
     89		dev_info(&pdev->dev, "Unknown IPMI class: %x\n", pdev->class);
     90		return -ENOMEM;
     91	}
     92
     93	rv = pcim_enable_device(pdev);
     94	if (rv) {
     95		dev_err(&pdev->dev, "couldn't enable PCI device\n");
     96		return rv;
     97	}
     98
     99	if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
    100		io.addr_space = IPMI_IO_ADDR_SPACE;
    101		io.io_setup = ipmi_si_port_setup;
    102	} else {
    103		io.addr_space = IPMI_MEM_ADDR_SPACE;
    104		io.io_setup = ipmi_si_mem_setup;
    105	}
    106	io.addr_data = pci_resource_start(pdev, 0);
    107
    108	io.dev = &pdev->dev;
    109
    110	io.regspacing = ipmi_pci_probe_regspacing(&io);
    111	io.regsize = DEFAULT_REGSIZE;
    112	io.regshift = 0;
    113
    114	io.irq = pdev->irq;
    115	if (io.irq)
    116		io.irq_setup = ipmi_std_irq_setup;
    117
    118	dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n",
    119		 &pdev->resource[0], io.regsize, io.regspacing, io.irq);
    120
    121	return ipmi_si_add_smi(&io);
    122}
    123
    124static void ipmi_pci_remove(struct pci_dev *pdev)
    125{
    126	ipmi_si_remove_by_dev(&pdev->dev);
    127}
    128
    129static const struct pci_device_id ipmi_pci_devices[] = {
    130	{ PCI_VDEVICE(HP, PCI_DEVICE_ID_HP_MMC) },
    131	{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_SMIC, ~0) },
    132	{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_KCS, ~0) },
    133	{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_BT, ~0) },
    134	{ 0, }
    135};
    136MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
    137
    138static struct pci_driver ipmi_pci_driver = {
    139	.name =         SI_DEVICE_NAME,
    140	.id_table =     ipmi_pci_devices,
    141	.probe =        ipmi_pci_probe,
    142	.remove =       ipmi_pci_remove,
    143};
    144
    145void ipmi_si_pci_init(void)
    146{
    147	if (si_trypci) {
    148		int rv = pci_register_driver(&ipmi_pci_driver);
    149		if (rv)
    150			pr_err("Unable to register PCI driver: %d\n", rv);
    151		else
    152			pci_registered = true;
    153	}
    154}
    155
    156void ipmi_si_pci_shutdown(void)
    157{
    158	if (pci_registered)
    159		pci_unregister_driver(&ipmi_pci_driver);
    160}