Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

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