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

amd8131_edac.c (10180B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * amd8131_edac.c, AMD8131 hypertransport chip EDAC kernel module
      4 *
      5 * Copyright (c) 2008 Wind River Systems, Inc.
      6 *
      7 * Authors:	Cao Qingtao <qingtao.cao@windriver.com>
      8 * 		Benjamin Walsh <benjamin.walsh@windriver.com>
      9 * 		Hu Yongqi <yongqi.hu@windriver.com>
     10 */
     11
     12#include <linux/module.h>
     13#include <linux/init.h>
     14#include <linux/interrupt.h>
     15#include <linux/io.h>
     16#include <linux/bitops.h>
     17#include <linux/edac.h>
     18#include <linux/pci_ids.h>
     19
     20#include "edac_module.h"
     21#include "amd8131_edac.h"
     22
     23#define AMD8131_EDAC_REVISION	" Ver: 1.0.0"
     24#define AMD8131_EDAC_MOD_STR	"amd8131_edac"
     25
     26/* Wrapper functions for accessing PCI configuration space */
     27static void edac_pci_read_dword(struct pci_dev *dev, int reg, u32 *val32)
     28{
     29	int ret;
     30
     31	ret = pci_read_config_dword(dev, reg, val32);
     32	if (ret != 0)
     33		printk(KERN_ERR AMD8131_EDAC_MOD_STR
     34			" PCI Access Read Error at 0x%x\n", reg);
     35}
     36
     37static void edac_pci_write_dword(struct pci_dev *dev, int reg, u32 val32)
     38{
     39	int ret;
     40
     41	ret = pci_write_config_dword(dev, reg, val32);
     42	if (ret != 0)
     43		printk(KERN_ERR AMD8131_EDAC_MOD_STR
     44			" PCI Access Write Error at 0x%x\n", reg);
     45}
     46
     47/* Support up to two AMD8131 chipsets on a platform */
     48static struct amd8131_dev_info amd8131_devices[] = {
     49	{
     50	.inst = NORTH_A,
     51	.devfn = DEVFN_PCIX_BRIDGE_NORTH_A,
     52	.ctl_name = "AMD8131_PCIX_NORTH_A",
     53	},
     54	{
     55	.inst = NORTH_B,
     56	.devfn = DEVFN_PCIX_BRIDGE_NORTH_B,
     57	.ctl_name = "AMD8131_PCIX_NORTH_B",
     58	},
     59	{
     60	.inst = SOUTH_A,
     61	.devfn = DEVFN_PCIX_BRIDGE_SOUTH_A,
     62	.ctl_name = "AMD8131_PCIX_SOUTH_A",
     63	},
     64	{
     65	.inst = SOUTH_B,
     66	.devfn = DEVFN_PCIX_BRIDGE_SOUTH_B,
     67	.ctl_name = "AMD8131_PCIX_SOUTH_B",
     68	},
     69	{.inst = NO_BRIDGE,},
     70};
     71
     72static void amd8131_pcix_init(struct amd8131_dev_info *dev_info)
     73{
     74	u32 val32;
     75	struct pci_dev *dev = dev_info->dev;
     76
     77	/* First clear error detection flags */
     78	edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
     79	if (val32 & MEM_LIMIT_MASK)
     80		edac_pci_write_dword(dev, REG_MEM_LIM, val32);
     81
     82	/* Clear Discard Timer Timedout flag */
     83	edac_pci_read_dword(dev, REG_INT_CTLR, &val32);
     84	if (val32 & INT_CTLR_DTS)
     85		edac_pci_write_dword(dev, REG_INT_CTLR, val32);
     86
     87	/* Clear CRC Error flag on link side A */
     88	edac_pci_read_dword(dev, REG_LNK_CTRL_A, &val32);
     89	if (val32 & LNK_CTRL_CRCERR_A)
     90		edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32);
     91
     92	/* Clear CRC Error flag on link side B */
     93	edac_pci_read_dword(dev, REG_LNK_CTRL_B, &val32);
     94	if (val32 & LNK_CTRL_CRCERR_B)
     95		edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32);
     96
     97	/*
     98	 * Then enable all error detections.
     99	 *
    100	 * Setup Discard Timer Sync Flood Enable,
    101	 * System Error Enable and Parity Error Enable.
    102	 */
    103	edac_pci_read_dword(dev, REG_INT_CTLR, &val32);
    104	val32 |= INT_CTLR_PERR | INT_CTLR_SERR | INT_CTLR_DTSE;
    105	edac_pci_write_dword(dev, REG_INT_CTLR, val32);
    106
    107	/* Enable overall SERR Error detection */
    108	edac_pci_read_dword(dev, REG_STS_CMD, &val32);
    109	val32 |= STS_CMD_SERREN;
    110	edac_pci_write_dword(dev, REG_STS_CMD, val32);
    111
    112	/* Setup CRC Flood Enable for link side A */
    113	edac_pci_read_dword(dev, REG_LNK_CTRL_A, &val32);
    114	val32 |= LNK_CTRL_CRCFEN;
    115	edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32);
    116
    117	/* Setup CRC Flood Enable for link side B */
    118	edac_pci_read_dword(dev, REG_LNK_CTRL_B, &val32);
    119	val32 |= LNK_CTRL_CRCFEN;
    120	edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32);
    121}
    122
    123static void amd8131_pcix_exit(struct amd8131_dev_info *dev_info)
    124{
    125	u32 val32;
    126	struct pci_dev *dev = dev_info->dev;
    127
    128	/* Disable SERR, PERR and DTSE Error detection */
    129	edac_pci_read_dword(dev, REG_INT_CTLR, &val32);
    130	val32 &= ~(INT_CTLR_PERR | INT_CTLR_SERR | INT_CTLR_DTSE);
    131	edac_pci_write_dword(dev, REG_INT_CTLR, val32);
    132
    133	/* Disable overall System Error detection */
    134	edac_pci_read_dword(dev, REG_STS_CMD, &val32);
    135	val32 &= ~STS_CMD_SERREN;
    136	edac_pci_write_dword(dev, REG_STS_CMD, val32);
    137
    138	/* Disable CRC Sync Flood on link side A */
    139	edac_pci_read_dword(dev, REG_LNK_CTRL_A, &val32);
    140	val32 &= ~LNK_CTRL_CRCFEN;
    141	edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32);
    142
    143	/* Disable CRC Sync Flood on link side B */
    144	edac_pci_read_dword(dev, REG_LNK_CTRL_B, &val32);
    145	val32 &= ~LNK_CTRL_CRCFEN;
    146	edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32);
    147}
    148
    149static void amd8131_pcix_check(struct edac_pci_ctl_info *edac_dev)
    150{
    151	struct amd8131_dev_info *dev_info = edac_dev->pvt_info;
    152	struct pci_dev *dev = dev_info->dev;
    153	u32 val32;
    154
    155	/* Check PCI-X Bridge Memory Base-Limit Register for errors */
    156	edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
    157	if (val32 & MEM_LIMIT_MASK) {
    158		printk(KERN_INFO "Error(s) in mem limit register "
    159			"on %s bridge\n", dev_info->ctl_name);
    160		printk(KERN_INFO "DPE: %d, RSE: %d, RMA: %d\n"
    161			"RTA: %d, STA: %d, MDPE: %d\n",
    162			val32 & MEM_LIMIT_DPE,
    163			val32 & MEM_LIMIT_RSE,
    164			val32 & MEM_LIMIT_RMA,
    165			val32 & MEM_LIMIT_RTA,
    166			val32 & MEM_LIMIT_STA,
    167			val32 & MEM_LIMIT_MDPE);
    168
    169		val32 |= MEM_LIMIT_MASK;
    170		edac_pci_write_dword(dev, REG_MEM_LIM, val32);
    171
    172		edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
    173	}
    174
    175	/* Check if Discard Timer timed out */
    176	edac_pci_read_dword(dev, REG_INT_CTLR, &val32);
    177	if (val32 & INT_CTLR_DTS) {
    178		printk(KERN_INFO "Error(s) in interrupt and control register "
    179			"on %s bridge\n", dev_info->ctl_name);
    180		printk(KERN_INFO "DTS: %d\n", val32 & INT_CTLR_DTS);
    181
    182		val32 |= INT_CTLR_DTS;
    183		edac_pci_write_dword(dev, REG_INT_CTLR, val32);
    184
    185		edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
    186	}
    187
    188	/* Check if CRC error happens on link side A */
    189	edac_pci_read_dword(dev, REG_LNK_CTRL_A, &val32);
    190	if (val32 & LNK_CTRL_CRCERR_A) {
    191		printk(KERN_INFO "Error(s) in link conf and control register "
    192			"on %s bridge\n", dev_info->ctl_name);
    193		printk(KERN_INFO "CRCERR: %d\n", val32 & LNK_CTRL_CRCERR_A);
    194
    195		val32 |= LNK_CTRL_CRCERR_A;
    196		edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32);
    197
    198		edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
    199	}
    200
    201	/* Check if CRC error happens on link side B */
    202	edac_pci_read_dword(dev, REG_LNK_CTRL_B, &val32);
    203	if (val32 & LNK_CTRL_CRCERR_B) {
    204		printk(KERN_INFO "Error(s) in link conf and control register "
    205			"on %s bridge\n", dev_info->ctl_name);
    206		printk(KERN_INFO "CRCERR: %d\n", val32 & LNK_CTRL_CRCERR_B);
    207
    208		val32 |= LNK_CTRL_CRCERR_B;
    209		edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32);
    210
    211		edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
    212	}
    213}
    214
    215static struct amd8131_info amd8131_chipset = {
    216	.err_dev = PCI_DEVICE_ID_AMD_8131_APIC,
    217	.devices = amd8131_devices,
    218	.init = amd8131_pcix_init,
    219	.exit = amd8131_pcix_exit,
    220	.check = amd8131_pcix_check,
    221};
    222
    223/*
    224 * There are 4 PCIX Bridges on ATCA-6101 that share the same PCI Device ID,
    225 * so amd8131_probe() would be called by kernel 4 times, with different
    226 * address of pci_dev for each of them each time.
    227 */
    228static int amd8131_probe(struct pci_dev *dev, const struct pci_device_id *id)
    229{
    230	struct amd8131_dev_info *dev_info;
    231
    232	for (dev_info = amd8131_chipset.devices; dev_info->inst != NO_BRIDGE;
    233		dev_info++)
    234		if (dev_info->devfn == dev->devfn)
    235			break;
    236
    237	if (dev_info->inst == NO_BRIDGE) /* should never happen */
    238		return -ENODEV;
    239
    240	/*
    241	 * We can't call pci_get_device() as we are used to do because
    242	 * there are 4 of them but pci_dev_get() instead.
    243	 */
    244	dev_info->dev = pci_dev_get(dev);
    245
    246	if (pci_enable_device(dev_info->dev)) {
    247		pci_dev_put(dev_info->dev);
    248		printk(KERN_ERR "failed to enable:"
    249			"vendor %x, device %x, devfn %x, name %s\n",
    250			PCI_VENDOR_ID_AMD, amd8131_chipset.err_dev,
    251			dev_info->devfn, dev_info->ctl_name);
    252		return -ENODEV;
    253	}
    254
    255	/*
    256	 * we do not allocate extra private structure for
    257	 * edac_pci_ctl_info, but make use of existing
    258	 * one instead.
    259	 */
    260	dev_info->edac_idx = edac_pci_alloc_index();
    261	dev_info->edac_dev = edac_pci_alloc_ctl_info(0, dev_info->ctl_name);
    262	if (!dev_info->edac_dev)
    263		return -ENOMEM;
    264
    265	dev_info->edac_dev->pvt_info = dev_info;
    266	dev_info->edac_dev->dev = &dev_info->dev->dev;
    267	dev_info->edac_dev->mod_name = AMD8131_EDAC_MOD_STR;
    268	dev_info->edac_dev->ctl_name = dev_info->ctl_name;
    269	dev_info->edac_dev->dev_name = dev_name(&dev_info->dev->dev);
    270
    271	if (edac_op_state == EDAC_OPSTATE_POLL)
    272		dev_info->edac_dev->edac_check = amd8131_chipset.check;
    273
    274	if (amd8131_chipset.init)
    275		amd8131_chipset.init(dev_info);
    276
    277	if (edac_pci_add_device(dev_info->edac_dev, dev_info->edac_idx) > 0) {
    278		printk(KERN_ERR "failed edac_pci_add_device() for %s\n",
    279			dev_info->ctl_name);
    280		edac_pci_free_ctl_info(dev_info->edac_dev);
    281		return -ENODEV;
    282	}
    283
    284	printk(KERN_INFO "added one device on AMD8131 "
    285		"vendor %x, device %x, devfn %x, name %s\n",
    286		PCI_VENDOR_ID_AMD, amd8131_chipset.err_dev,
    287		dev_info->devfn, dev_info->ctl_name);
    288
    289	return 0;
    290}
    291
    292static void amd8131_remove(struct pci_dev *dev)
    293{
    294	struct amd8131_dev_info *dev_info;
    295
    296	for (dev_info = amd8131_chipset.devices; dev_info->inst != NO_BRIDGE;
    297		dev_info++)
    298		if (dev_info->devfn == dev->devfn)
    299			break;
    300
    301	if (dev_info->inst == NO_BRIDGE) /* should never happen */
    302		return;
    303
    304	if (dev_info->edac_dev) {
    305		edac_pci_del_device(dev_info->edac_dev->dev);
    306		edac_pci_free_ctl_info(dev_info->edac_dev);
    307	}
    308
    309	if (amd8131_chipset.exit)
    310		amd8131_chipset.exit(dev_info);
    311
    312	pci_dev_put(dev_info->dev);
    313}
    314
    315static const struct pci_device_id amd8131_edac_pci_tbl[] = {
    316	{
    317	PCI_VEND_DEV(AMD, 8131_BRIDGE),
    318	.subvendor = PCI_ANY_ID,
    319	.subdevice = PCI_ANY_ID,
    320	.class = 0,
    321	.class_mask = 0,
    322	.driver_data = 0,
    323	},
    324	{
    325	0,
    326	}			/* table is NULL-terminated */
    327};
    328MODULE_DEVICE_TABLE(pci, amd8131_edac_pci_tbl);
    329
    330static struct pci_driver amd8131_edac_driver = {
    331	.name = AMD8131_EDAC_MOD_STR,
    332	.probe = amd8131_probe,
    333	.remove = amd8131_remove,
    334	.id_table = amd8131_edac_pci_tbl,
    335};
    336
    337static int __init amd8131_edac_init(void)
    338{
    339	printk(KERN_INFO "AMD8131 EDAC driver " AMD8131_EDAC_REVISION "\n");
    340	printk(KERN_INFO "\t(c) 2008 Wind River Systems, Inc.\n");
    341
    342	/* Only POLL mode supported so far */
    343	edac_op_state = EDAC_OPSTATE_POLL;
    344
    345	return pci_register_driver(&amd8131_edac_driver);
    346}
    347
    348static void __exit amd8131_edac_exit(void)
    349{
    350	pci_unregister_driver(&amd8131_edac_driver);
    351}
    352
    353module_init(amd8131_edac_init);
    354module_exit(amd8131_edac_exit);
    355
    356MODULE_LICENSE("GPL");
    357MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>\n");
    358MODULE_DESCRIPTION("AMD8131 HyperTransport PCI-X Tunnel EDAC kernel module");