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

portdrv_core.c (16505B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Purpose:	PCI Express Port Bus Driver's Core Functions
      4 *
      5 * Copyright (C) 2004 Intel
      6 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/pci.h>
     11#include <linux/kernel.h>
     12#include <linux/errno.h>
     13#include <linux/pm.h>
     14#include <linux/pm_runtime.h>
     15#include <linux/string.h>
     16#include <linux/slab.h>
     17#include <linux/aer.h>
     18
     19#include "../pci.h"
     20#include "portdrv.h"
     21
     22struct portdrv_service_data {
     23	struct pcie_port_service_driver *drv;
     24	struct device *dev;
     25	u32 service;
     26};
     27
     28/**
     29 * release_pcie_device - free PCI Express port service device structure
     30 * @dev: Port service device to release
     31 *
     32 * Invoked automatically when device is being removed in response to
     33 * device_unregister(dev).  Release all resources being claimed.
     34 */
     35static void release_pcie_device(struct device *dev)
     36{
     37	kfree(to_pcie_device(dev));
     38}
     39
     40/*
     41 * Fill in *pme, *aer, *dpc with the relevant Interrupt Message Numbers if
     42 * services are enabled in "mask".  Return the number of MSI/MSI-X vectors
     43 * required to accommodate the largest Message Number.
     44 */
     45static int pcie_message_numbers(struct pci_dev *dev, int mask,
     46				u32 *pme, u32 *aer, u32 *dpc)
     47{
     48	u32 nvec = 0, pos;
     49	u16 reg16;
     50
     51	/*
     52	 * The Interrupt Message Number indicates which vector is used, i.e.,
     53	 * the MSI-X table entry or the MSI offset between the base Message
     54	 * Data and the generated interrupt message.  See PCIe r3.1, sec
     55	 * 7.8.2, 7.10.10, 7.31.2.
     56	 */
     57
     58	if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP |
     59		    PCIE_PORT_SERVICE_BWNOTIF)) {
     60		pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
     61		*pme = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
     62		nvec = *pme + 1;
     63	}
     64
     65#ifdef CONFIG_PCIEAER
     66	if (mask & PCIE_PORT_SERVICE_AER) {
     67		u32 reg32;
     68
     69		pos = dev->aer_cap;
     70		if (pos) {
     71			pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS,
     72					      &reg32);
     73			*aer = (reg32 & PCI_ERR_ROOT_AER_IRQ) >> 27;
     74			nvec = max(nvec, *aer + 1);
     75		}
     76	}
     77#endif
     78
     79	if (mask & PCIE_PORT_SERVICE_DPC) {
     80		pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC);
     81		if (pos) {
     82			pci_read_config_word(dev, pos + PCI_EXP_DPC_CAP,
     83					     &reg16);
     84			*dpc = reg16 & PCI_EXP_DPC_IRQ;
     85			nvec = max(nvec, *dpc + 1);
     86		}
     87	}
     88
     89	return nvec;
     90}
     91
     92/**
     93 * pcie_port_enable_irq_vec - try to set up MSI-X or MSI as interrupt mode
     94 * for given port
     95 * @dev: PCI Express port to handle
     96 * @irqs: Array of interrupt vectors to populate
     97 * @mask: Bitmask of port capabilities returned by get_port_device_capability()
     98 *
     99 * Return value: 0 on success, error code on failure
    100 */
    101static int pcie_port_enable_irq_vec(struct pci_dev *dev, int *irqs, int mask)
    102{
    103	int nr_entries, nvec, pcie_irq;
    104	u32 pme = 0, aer = 0, dpc = 0;
    105
    106	/* Allocate the maximum possible number of MSI/MSI-X vectors */
    107	nr_entries = pci_alloc_irq_vectors(dev, 1, PCIE_PORT_MAX_MSI_ENTRIES,
    108			PCI_IRQ_MSIX | PCI_IRQ_MSI);
    109	if (nr_entries < 0)
    110		return nr_entries;
    111
    112	/* See how many and which Interrupt Message Numbers we actually use */
    113	nvec = pcie_message_numbers(dev, mask, &pme, &aer, &dpc);
    114	if (nvec > nr_entries) {
    115		pci_free_irq_vectors(dev);
    116		return -EIO;
    117	}
    118
    119	/*
    120	 * If we allocated more than we need, free them and reallocate fewer.
    121	 *
    122	 * Reallocating may change the specific vectors we get, so
    123	 * pci_irq_vector() must be done *after* the reallocation.
    124	 *
    125	 * If we're using MSI, hardware is *allowed* to change the Interrupt
    126	 * Message Numbers when we free and reallocate the vectors, but we
    127	 * assume it won't because we allocate enough vectors for the
    128	 * biggest Message Number we found.
    129	 */
    130	if (nvec != nr_entries) {
    131		pci_free_irq_vectors(dev);
    132
    133		nr_entries = pci_alloc_irq_vectors(dev, nvec, nvec,
    134				PCI_IRQ_MSIX | PCI_IRQ_MSI);
    135		if (nr_entries < 0)
    136			return nr_entries;
    137	}
    138
    139	/* PME, hotplug and bandwidth notification share an MSI/MSI-X vector */
    140	if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP |
    141		    PCIE_PORT_SERVICE_BWNOTIF)) {
    142		pcie_irq = pci_irq_vector(dev, pme);
    143		irqs[PCIE_PORT_SERVICE_PME_SHIFT] = pcie_irq;
    144		irqs[PCIE_PORT_SERVICE_HP_SHIFT] = pcie_irq;
    145		irqs[PCIE_PORT_SERVICE_BWNOTIF_SHIFT] = pcie_irq;
    146	}
    147
    148	if (mask & PCIE_PORT_SERVICE_AER)
    149		irqs[PCIE_PORT_SERVICE_AER_SHIFT] = pci_irq_vector(dev, aer);
    150
    151	if (mask & PCIE_PORT_SERVICE_DPC)
    152		irqs[PCIE_PORT_SERVICE_DPC_SHIFT] = pci_irq_vector(dev, dpc);
    153
    154	return 0;
    155}
    156
    157/**
    158 * pcie_init_service_irqs - initialize irqs for PCI Express port services
    159 * @dev: PCI Express port to handle
    160 * @irqs: Array of irqs to populate
    161 * @mask: Bitmask of port capabilities returned by get_port_device_capability()
    162 *
    163 * Return value: Interrupt mode associated with the port
    164 */
    165static int pcie_init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
    166{
    167	int ret, i;
    168
    169	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
    170		irqs[i] = -1;
    171
    172	/*
    173	 * If we support PME but can't use MSI/MSI-X for it, we have to
    174	 * fall back to INTx or other interrupts, e.g., a system shared
    175	 * interrupt.
    176	 */
    177	if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi())
    178		goto legacy_irq;
    179
    180	/* Try to use MSI-X or MSI if supported */
    181	if (pcie_port_enable_irq_vec(dev, irqs, mask) == 0)
    182		return 0;
    183
    184legacy_irq:
    185	/* fall back to legacy IRQ */
    186	ret = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY);
    187	if (ret < 0)
    188		return -ENODEV;
    189
    190	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
    191		irqs[i] = pci_irq_vector(dev, 0);
    192
    193	return 0;
    194}
    195
    196/**
    197 * get_port_device_capability - discover capabilities of a PCI Express port
    198 * @dev: PCI Express port to examine
    199 *
    200 * The capabilities are read from the port's PCI Express configuration registers
    201 * as described in PCI Express Base Specification 1.0a sections 7.8.2, 7.8.9 and
    202 * 7.9 - 7.11.
    203 *
    204 * Return value: Bitmask of discovered port capabilities
    205 */
    206static int get_port_device_capability(struct pci_dev *dev)
    207{
    208	struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
    209	int services = 0;
    210
    211	if (dev->is_hotplug_bridge &&
    212	    (pcie_ports_native || host->native_pcie_hotplug)) {
    213		services |= PCIE_PORT_SERVICE_HP;
    214
    215		/*
    216		 * Disable hot-plug interrupts in case they have been enabled
    217		 * by the BIOS and the hot-plug service driver is not loaded.
    218		 */
    219		pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
    220			  PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
    221	}
    222
    223#ifdef CONFIG_PCIEAER
    224	if (dev->aer_cap && pci_aer_available() &&
    225	    (pcie_ports_native || host->native_aer)) {
    226		services |= PCIE_PORT_SERVICE_AER;
    227
    228		/*
    229		 * Disable AER on this port in case it's been enabled by the
    230		 * BIOS (the AER service driver will enable it when necessary).
    231		 */
    232		pci_disable_pcie_error_reporting(dev);
    233	}
    234#endif
    235
    236	/* Root Ports and Root Complex Event Collectors may generate PMEs */
    237	if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
    238	     pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC) &&
    239	    (pcie_ports_native || host->native_pme)) {
    240		services |= PCIE_PORT_SERVICE_PME;
    241
    242		/*
    243		 * Disable PME interrupt on this port in case it's been enabled
    244		 * by the BIOS (the PME service driver will enable it when
    245		 * necessary).
    246		 */
    247		pcie_pme_interrupt_enable(dev, false);
    248	}
    249
    250	/*
    251	 * With dpc-native, allow Linux to use DPC even if it doesn't have
    252	 * permission to use AER.
    253	 */
    254	if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC) &&
    255	    pci_aer_available() &&
    256	    (pcie_ports_dpc_native || (services & PCIE_PORT_SERVICE_AER)))
    257		services |= PCIE_PORT_SERVICE_DPC;
    258
    259	if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM ||
    260	    pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
    261		u32 linkcap;
    262
    263		pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &linkcap);
    264		if (linkcap & PCI_EXP_LNKCAP_LBNC)
    265			services |= PCIE_PORT_SERVICE_BWNOTIF;
    266	}
    267
    268	return services;
    269}
    270
    271/**
    272 * pcie_device_init - allocate and initialize PCI Express port service device
    273 * @pdev: PCI Express port to associate the service device with
    274 * @service: Type of service to associate with the service device
    275 * @irq: Interrupt vector to associate with the service device
    276 */
    277static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
    278{
    279	int retval;
    280	struct pcie_device *pcie;
    281	struct device *device;
    282
    283	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
    284	if (!pcie)
    285		return -ENOMEM;
    286	pcie->port = pdev;
    287	pcie->irq = irq;
    288	pcie->service = service;
    289
    290	/* Initialize generic device interface */
    291	device = &pcie->device;
    292	device->bus = &pcie_port_bus_type;
    293	device->release = release_pcie_device;	/* callback to free pcie dev */
    294	dev_set_name(device, "%s:pcie%03x",
    295		     pci_name(pdev),
    296		     get_descriptor_id(pci_pcie_type(pdev), service));
    297	device->parent = &pdev->dev;
    298	device_enable_async_suspend(device);
    299
    300	retval = device_register(device);
    301	if (retval) {
    302		put_device(device);
    303		return retval;
    304	}
    305
    306	pm_runtime_no_callbacks(device);
    307
    308	return 0;
    309}
    310
    311/**
    312 * pcie_port_device_register - register PCI Express port
    313 * @dev: PCI Express port to register
    314 *
    315 * Allocate the port extension structure and register services associated with
    316 * the port.
    317 */
    318int pcie_port_device_register(struct pci_dev *dev)
    319{
    320	int status, capabilities, i, nr_service;
    321	int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
    322
    323	/* Enable PCI Express port device */
    324	status = pci_enable_device(dev);
    325	if (status)
    326		return status;
    327
    328	/* Get and check PCI Express port services */
    329	capabilities = get_port_device_capability(dev);
    330	if (!capabilities)
    331		return 0;
    332
    333	pci_set_master(dev);
    334	/*
    335	 * Initialize service irqs. Don't use service devices that
    336	 * require interrupts if there is no way to generate them.
    337	 * However, some drivers may have a polling mode (e.g. pciehp_poll_mode)
    338	 * that can be used in the absence of irqs.  Allow them to determine
    339	 * if that is to be used.
    340	 */
    341	status = pcie_init_service_irqs(dev, irqs, capabilities);
    342	if (status) {
    343		capabilities &= PCIE_PORT_SERVICE_HP;
    344		if (!capabilities)
    345			goto error_disable;
    346	}
    347
    348	/* Allocate child services if any */
    349	status = -ENODEV;
    350	nr_service = 0;
    351	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
    352		int service = 1 << i;
    353		if (!(capabilities & service))
    354			continue;
    355		if (!pcie_device_init(dev, service, irqs[i]))
    356			nr_service++;
    357	}
    358	if (!nr_service)
    359		goto error_cleanup_irqs;
    360
    361	return 0;
    362
    363error_cleanup_irqs:
    364	pci_free_irq_vectors(dev);
    365error_disable:
    366	pci_disable_device(dev);
    367	return status;
    368}
    369
    370typedef int (*pcie_callback_t)(struct pcie_device *);
    371
    372int pcie_port_device_iter(struct device *dev, void *data)
    373{
    374	struct pcie_port_service_driver *service_driver;
    375	size_t offset = *(size_t *)data;
    376	pcie_callback_t cb;
    377
    378	if ((dev->bus == &pcie_port_bus_type) && dev->driver) {
    379		service_driver = to_service_driver(dev->driver);
    380		cb = *(pcie_callback_t *)((void *)service_driver + offset);
    381		if (cb)
    382			return cb(to_pcie_device(dev));
    383	}
    384	return 0;
    385}
    386
    387#ifdef CONFIG_PM
    388/**
    389 * pcie_port_device_suspend - suspend port services associated with a PCIe port
    390 * @dev: PCI Express port to handle
    391 */
    392int pcie_port_device_suspend(struct device *dev)
    393{
    394	size_t off = offsetof(struct pcie_port_service_driver, suspend);
    395	return device_for_each_child(dev, &off, pcie_port_device_iter);
    396}
    397
    398int pcie_port_device_resume_noirq(struct device *dev)
    399{
    400	size_t off = offsetof(struct pcie_port_service_driver, resume_noirq);
    401	return device_for_each_child(dev, &off, pcie_port_device_iter);
    402}
    403
    404/**
    405 * pcie_port_device_resume - resume port services associated with a PCIe port
    406 * @dev: PCI Express port to handle
    407 */
    408int pcie_port_device_resume(struct device *dev)
    409{
    410	size_t off = offsetof(struct pcie_port_service_driver, resume);
    411	return device_for_each_child(dev, &off, pcie_port_device_iter);
    412}
    413
    414/**
    415 * pcie_port_device_runtime_suspend - runtime suspend port services
    416 * @dev: PCI Express port to handle
    417 */
    418int pcie_port_device_runtime_suspend(struct device *dev)
    419{
    420	size_t off = offsetof(struct pcie_port_service_driver, runtime_suspend);
    421	return device_for_each_child(dev, &off, pcie_port_device_iter);
    422}
    423
    424/**
    425 * pcie_port_device_runtime_resume - runtime resume port services
    426 * @dev: PCI Express port to handle
    427 */
    428int pcie_port_device_runtime_resume(struct device *dev)
    429{
    430	size_t off = offsetof(struct pcie_port_service_driver, runtime_resume);
    431	return device_for_each_child(dev, &off, pcie_port_device_iter);
    432}
    433#endif /* PM */
    434
    435static int remove_iter(struct device *dev, void *data)
    436{
    437	if (dev->bus == &pcie_port_bus_type)
    438		device_unregister(dev);
    439	return 0;
    440}
    441
    442static int find_service_iter(struct device *device, void *data)
    443{
    444	struct pcie_port_service_driver *service_driver;
    445	struct portdrv_service_data *pdrvs;
    446	u32 service;
    447
    448	pdrvs = (struct portdrv_service_data *) data;
    449	service = pdrvs->service;
    450
    451	if (device->bus == &pcie_port_bus_type && device->driver) {
    452		service_driver = to_service_driver(device->driver);
    453		if (service_driver->service == service) {
    454			pdrvs->drv = service_driver;
    455			pdrvs->dev = device;
    456			return 1;
    457		}
    458	}
    459
    460	return 0;
    461}
    462
    463/**
    464 * pcie_port_find_device - find the struct device
    465 * @dev: PCI Express port the service is associated with
    466 * @service: For the service to find
    467 *
    468 * Find the struct device associated with given service on a pci_dev
    469 */
    470struct device *pcie_port_find_device(struct pci_dev *dev,
    471				      u32 service)
    472{
    473	struct device *device;
    474	struct portdrv_service_data pdrvs;
    475
    476	pdrvs.dev = NULL;
    477	pdrvs.service = service;
    478	device_for_each_child(&dev->dev, &pdrvs, find_service_iter);
    479
    480	device = pdrvs.dev;
    481	return device;
    482}
    483EXPORT_SYMBOL_GPL(pcie_port_find_device);
    484
    485/**
    486 * pcie_port_device_remove - unregister PCI Express port service devices
    487 * @dev: PCI Express port the service devices to unregister are associated with
    488 *
    489 * Remove PCI Express port service devices associated with given port and
    490 * disable MSI-X or MSI for the port.
    491 */
    492void pcie_port_device_remove(struct pci_dev *dev)
    493{
    494	device_for_each_child(&dev->dev, NULL, remove_iter);
    495	pci_free_irq_vectors(dev);
    496	pci_disable_device(dev);
    497}
    498
    499/**
    500 * pcie_port_probe_service - probe driver for given PCI Express port service
    501 * @dev: PCI Express port service device to probe against
    502 *
    503 * If PCI Express port service driver is registered with
    504 * pcie_port_service_register(), this function will be called by the driver core
    505 * whenever match is found between the driver and a port service device.
    506 */
    507static int pcie_port_probe_service(struct device *dev)
    508{
    509	struct pcie_device *pciedev;
    510	struct pcie_port_service_driver *driver;
    511	int status;
    512
    513	if (!dev || !dev->driver)
    514		return -ENODEV;
    515
    516	driver = to_service_driver(dev->driver);
    517	if (!driver || !driver->probe)
    518		return -ENODEV;
    519
    520	pciedev = to_pcie_device(dev);
    521	status = driver->probe(pciedev);
    522	if (status)
    523		return status;
    524
    525	get_device(dev);
    526	return 0;
    527}
    528
    529/**
    530 * pcie_port_remove_service - detach driver from given PCI Express port service
    531 * @dev: PCI Express port service device to handle
    532 *
    533 * If PCI Express port service driver is registered with
    534 * pcie_port_service_register(), this function will be called by the driver core
    535 * when device_unregister() is called for the port service device associated
    536 * with the driver.
    537 */
    538static int pcie_port_remove_service(struct device *dev)
    539{
    540	struct pcie_device *pciedev;
    541	struct pcie_port_service_driver *driver;
    542
    543	if (!dev || !dev->driver)
    544		return 0;
    545
    546	pciedev = to_pcie_device(dev);
    547	driver = to_service_driver(dev->driver);
    548	if (driver && driver->remove) {
    549		driver->remove(pciedev);
    550		put_device(dev);
    551	}
    552	return 0;
    553}
    554
    555/**
    556 * pcie_port_shutdown_service - shut down given PCI Express port service
    557 * @dev: PCI Express port service device to handle
    558 *
    559 * If PCI Express port service driver is registered with
    560 * pcie_port_service_register(), this function will be called by the driver core
    561 * when device_shutdown() is called for the port service device associated
    562 * with the driver.
    563 */
    564static void pcie_port_shutdown_service(struct device *dev) {}
    565
    566/**
    567 * pcie_port_service_register - register PCI Express port service driver
    568 * @new: PCI Express port service driver to register
    569 */
    570int pcie_port_service_register(struct pcie_port_service_driver *new)
    571{
    572	if (pcie_ports_disabled)
    573		return -ENODEV;
    574
    575	new->driver.name = new->name;
    576	new->driver.bus = &pcie_port_bus_type;
    577	new->driver.probe = pcie_port_probe_service;
    578	new->driver.remove = pcie_port_remove_service;
    579	new->driver.shutdown = pcie_port_shutdown_service;
    580
    581	return driver_register(&new->driver);
    582}
    583EXPORT_SYMBOL(pcie_port_service_register);
    584
    585/**
    586 * pcie_port_service_unregister - unregister PCI Express port service driver
    587 * @drv: PCI Express port service driver to unregister
    588 */
    589void pcie_port_service_unregister(struct pcie_port_service_driver *drv)
    590{
    591	driver_unregister(&drv->driver);
    592}
    593EXPORT_SYMBOL(pcie_port_service_unregister);