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

cpci_hotplug_pci.c (6405B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * CompactPCI Hot Plug Driver PCI functions
      4 *
      5 * Copyright (C) 2002,2005 by SOMA Networks, Inc.
      6 *
      7 * All rights reserved.
      8 *
      9 * Send feedback to <scottm@somanetworks.com>
     10 */
     11
     12#include <linux/module.h>
     13#include <linux/kernel.h>
     14#include <linux/pci.h>
     15#include <linux/pci_hotplug.h>
     16#include <linux/proc_fs.h>
     17#include "../pci.h"
     18#include "cpci_hotplug.h"
     19
     20#define MY_NAME	"cpci_hotplug"
     21
     22#define dbg(format, arg...)					\
     23	do {							\
     24		if (cpci_debug)					\
     25			printk(KERN_DEBUG "%s: " format "\n",	\
     26				MY_NAME, ## arg);		\
     27	} while (0)
     28#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
     29#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
     30#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
     31
     32
     33u8 cpci_get_attention_status(struct slot *slot)
     34{
     35	int hs_cap;
     36	u16 hs_csr;
     37
     38	hs_cap = pci_bus_find_capability(slot->bus,
     39					 slot->devfn,
     40					 PCI_CAP_ID_CHSWP);
     41	if (!hs_cap)
     42		return 0;
     43
     44	if (pci_bus_read_config_word(slot->bus,
     45				     slot->devfn,
     46				     hs_cap + 2,
     47				     &hs_csr))
     48		return 0;
     49
     50	return hs_csr & 0x0008 ? 1 : 0;
     51}
     52
     53int cpci_set_attention_status(struct slot *slot, int status)
     54{
     55	int hs_cap;
     56	u16 hs_csr;
     57
     58	hs_cap = pci_bus_find_capability(slot->bus,
     59					 slot->devfn,
     60					 PCI_CAP_ID_CHSWP);
     61	if (!hs_cap)
     62		return 0;
     63	if (pci_bus_read_config_word(slot->bus,
     64				     slot->devfn,
     65				     hs_cap + 2,
     66				     &hs_csr))
     67		return 0;
     68	if (status)
     69		hs_csr |= HS_CSR_LOO;
     70	else
     71		hs_csr &= ~HS_CSR_LOO;
     72	if (pci_bus_write_config_word(slot->bus,
     73				      slot->devfn,
     74				      hs_cap + 2,
     75				      hs_csr))
     76		return 0;
     77	return 1;
     78}
     79
     80u16 cpci_get_hs_csr(struct slot *slot)
     81{
     82	int hs_cap;
     83	u16 hs_csr;
     84
     85	hs_cap = pci_bus_find_capability(slot->bus,
     86					 slot->devfn,
     87					 PCI_CAP_ID_CHSWP);
     88	if (!hs_cap)
     89		return 0xFFFF;
     90	if (pci_bus_read_config_word(slot->bus,
     91				     slot->devfn,
     92				     hs_cap + 2,
     93				     &hs_csr))
     94		return 0xFFFF;
     95	return hs_csr;
     96}
     97
     98int cpci_check_and_clear_ins(struct slot *slot)
     99{
    100	int hs_cap;
    101	u16 hs_csr;
    102	int ins = 0;
    103
    104	hs_cap = pci_bus_find_capability(slot->bus,
    105					 slot->devfn,
    106					 PCI_CAP_ID_CHSWP);
    107	if (!hs_cap)
    108		return 0;
    109	if (pci_bus_read_config_word(slot->bus,
    110				     slot->devfn,
    111				     hs_cap + 2,
    112				     &hs_csr))
    113		return 0;
    114	if (hs_csr & HS_CSR_INS) {
    115		/* Clear INS (by setting it) */
    116		if (pci_bus_write_config_word(slot->bus,
    117					      slot->devfn,
    118					      hs_cap + 2,
    119					      hs_csr))
    120			ins = 0;
    121		else
    122			ins = 1;
    123	}
    124	return ins;
    125}
    126
    127int cpci_check_ext(struct slot *slot)
    128{
    129	int hs_cap;
    130	u16 hs_csr;
    131	int ext = 0;
    132
    133	hs_cap = pci_bus_find_capability(slot->bus,
    134					 slot->devfn,
    135					 PCI_CAP_ID_CHSWP);
    136	if (!hs_cap)
    137		return 0;
    138	if (pci_bus_read_config_word(slot->bus,
    139				     slot->devfn,
    140				     hs_cap + 2,
    141				     &hs_csr))
    142		return 0;
    143	if (hs_csr & HS_CSR_EXT)
    144		ext = 1;
    145	return ext;
    146}
    147
    148int cpci_clear_ext(struct slot *slot)
    149{
    150	int hs_cap;
    151	u16 hs_csr;
    152
    153	hs_cap = pci_bus_find_capability(slot->bus,
    154					 slot->devfn,
    155					 PCI_CAP_ID_CHSWP);
    156	if (!hs_cap)
    157		return -ENODEV;
    158	if (pci_bus_read_config_word(slot->bus,
    159				     slot->devfn,
    160				     hs_cap + 2,
    161				     &hs_csr))
    162		return -ENODEV;
    163	if (hs_csr & HS_CSR_EXT) {
    164		/* Clear EXT (by setting it) */
    165		if (pci_bus_write_config_word(slot->bus,
    166					      slot->devfn,
    167					      hs_cap + 2,
    168					      hs_csr))
    169			return -ENODEV;
    170	}
    171	return 0;
    172}
    173
    174int cpci_led_on(struct slot *slot)
    175{
    176	int hs_cap;
    177	u16 hs_csr;
    178
    179	hs_cap = pci_bus_find_capability(slot->bus,
    180					 slot->devfn,
    181					 PCI_CAP_ID_CHSWP);
    182	if (!hs_cap)
    183		return -ENODEV;
    184	if (pci_bus_read_config_word(slot->bus,
    185				     slot->devfn,
    186				     hs_cap + 2,
    187				     &hs_csr))
    188		return -ENODEV;
    189	if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
    190		hs_csr |= HS_CSR_LOO;
    191		if (pci_bus_write_config_word(slot->bus,
    192					      slot->devfn,
    193					      hs_cap + 2,
    194					      hs_csr)) {
    195			err("Could not set LOO for slot %s", slot_name(slot));
    196			return -ENODEV;
    197		}
    198	}
    199	return 0;
    200}
    201
    202int cpci_led_off(struct slot *slot)
    203{
    204	int hs_cap;
    205	u16 hs_csr;
    206
    207	hs_cap = pci_bus_find_capability(slot->bus,
    208					 slot->devfn,
    209					 PCI_CAP_ID_CHSWP);
    210	if (!hs_cap)
    211		return -ENODEV;
    212	if (pci_bus_read_config_word(slot->bus,
    213				     slot->devfn,
    214				     hs_cap + 2,
    215				     &hs_csr))
    216		return -ENODEV;
    217	if (hs_csr & HS_CSR_LOO) {
    218		hs_csr &= ~HS_CSR_LOO;
    219		if (pci_bus_write_config_word(slot->bus,
    220					      slot->devfn,
    221					      hs_cap + 2,
    222					      hs_csr)) {
    223			err("Could not clear LOO for slot %s", slot_name(slot));
    224			return -ENODEV;
    225		}
    226	}
    227	return 0;
    228}
    229
    230
    231/*
    232 * Device configuration functions
    233 */
    234
    235int cpci_configure_slot(struct slot *slot)
    236{
    237	struct pci_dev *dev;
    238	struct pci_bus *parent;
    239	int ret = 0;
    240
    241	dbg("%s - enter", __func__);
    242
    243	pci_lock_rescan_remove();
    244
    245	if (slot->dev == NULL) {
    246		dbg("pci_dev null, finding %02x:%02x:%x",
    247		    slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
    248		slot->dev = pci_get_slot(slot->bus, slot->devfn);
    249	}
    250
    251	/* Still NULL? Well then scan for it! */
    252	if (slot->dev == NULL) {
    253		int n;
    254		dbg("pci_dev still null");
    255
    256		/*
    257		 * This will generate pci_dev structures for all functions, but
    258		 * we will only call this case when lookup fails.
    259		 */
    260		n = pci_scan_slot(slot->bus, slot->devfn);
    261		dbg("%s: pci_scan_slot returned %d", __func__, n);
    262		slot->dev = pci_get_slot(slot->bus, slot->devfn);
    263		if (slot->dev == NULL) {
    264			err("Could not find PCI device for slot %02x", slot->number);
    265			ret = -ENODEV;
    266			goto out;
    267		}
    268	}
    269	parent = slot->dev->bus;
    270
    271	for_each_pci_bridge(dev, parent) {
    272		if (PCI_SLOT(dev->devfn) == PCI_SLOT(slot->devfn))
    273			pci_hp_add_bridge(dev);
    274	}
    275
    276	pci_assign_unassigned_bridge_resources(parent->self);
    277
    278	pci_bus_add_devices(parent);
    279
    280 out:
    281	pci_unlock_rescan_remove();
    282	dbg("%s - exit", __func__);
    283	return ret;
    284}
    285
    286int cpci_unconfigure_slot(struct slot *slot)
    287{
    288	struct pci_dev *dev, *temp;
    289
    290	dbg("%s - enter", __func__);
    291	if (!slot->dev) {
    292		err("No device for slot %02x\n", slot->number);
    293		return -ENODEV;
    294	}
    295
    296	pci_lock_rescan_remove();
    297
    298	list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) {
    299		if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
    300			continue;
    301		pci_dev_get(dev);
    302		pci_stop_and_remove_bus_device(dev);
    303		pci_dev_put(dev);
    304	}
    305	pci_dev_put(slot->dev);
    306	slot->dev = NULL;
    307
    308	pci_unlock_rescan_remove();
    309
    310	dbg("%s - exit", __func__);
    311	return 0;
    312}