Commit 37f04581 authored by Doug Thompson's avatar Doug Thompson Committed by Linus Torvalds
Browse files

[PATCH] EDAC: PCI device to DEVICE cleanup



Change MC drivers from using CVS revision strings for their version number,
Now each driver has its own local string.

Remove some PCI dependencies from the core EDAC module.  Made the code 'struct
device' centric instead of 'struct pci_dev' Most of the code changes here are
from a patch by Dave Jiang.  It may be best to eventually move the
PCI-specific code into a separate source file.
Signed-off-by: default avatarDoug Thompson <norsk5@xmission.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent dc474c89
......@@ -20,6 +20,9 @@
#include <linux/slab.h>
#include "edac_mc.h"
#define AMD76X_REVISION " Ver: 2.0.0 " __DATE__
#define amd76x_printk(level, fmt, arg...) \
edac_printk(level, "amd76x", fmt, ##arg)
......@@ -102,15 +105,18 @@ static const struct amd76x_dev_info amd76x_devs[] = {
static void amd76x_get_error_info(struct mem_ctl_info *mci,
struct amd76x_error_info *info)
{
pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS,
struct pci_dev *pdev;
pdev = to_pci_dev(mci->dev);
pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS,
&info->ecc_mode_status);
if (info->ecc_mode_status & BIT(8))
pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS,
(u32) BIT(8), (u32) BIT(8));
if (info->ecc_mode_status & BIT(9))
pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS,
(u32) BIT(9), (u32) BIT(9));
}
......@@ -211,13 +217,13 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
}
debugf0("%s(): mci = %p\n", __func__, mci);
mci->pdev = pdev;
mci->dev = &pdev->dev;
mci->mtype_cap = MEM_FLAG_RDDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
mci->edac_cap = ems_mode ?
(EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.4.2.5 $";
mci->mod_ver = AMD76X_REVISION;
mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
mci->edac_check = amd76x_check;
mci->ctl_page_to_phys = NULL;
......@@ -230,7 +236,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
u32 dms;
/* find the DRAM Chip Select Base address and mask */
pci_read_config_dword(mci->pdev,
pci_read_config_dword(pdev,
AMD76X_MEM_BASE_ADDR + (index * 4), &mba);
if (!(mba & BIT(0)))
......@@ -238,8 +244,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
mba_base = mba & 0xff800000UL;
mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS,
&dms);
pci_read_config_dword(pdev, AMD76X_DRAM_MODE_STATUS, &dms);
csrow->first_page = mba_base >> PAGE_SHIFT;
csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
......@@ -291,7 +296,7 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev)
debugf0("%s()\n", __func__);
if ((mci = edac_mc_del_mc(pdev)) == NULL)
if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
return;
edac_mc_free(mci);
......
......@@ -25,6 +25,8 @@
#include <linux/slab.h>
#include "edac_mc.h"
#define E752X_REVISION " Ver: 2.0.0 " __DATE__
static int force_function_unhide;
#define e752x_printk(level, fmt, arg...) \
......@@ -819,8 +821,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
EDAC_FLAG_S4ECD4ED;
/* FIXME - what if different memory types are in different csrows? */
mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.5.2.11 $";
mci->pdev = pdev;
mci->mod_ver = E752X_REVISION;
mci->dev = &pdev->dev;
debugf3("%s(): init pvt\n", __func__);
pvt = (struct e752x_pvt *) mci->pvt_info;
......@@ -864,7 +866,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
struct csrow_info *csrow = &mci->csrows[index];
mem_dev = (mem_dev == 2);
pci_read_config_byte(mci->pdev, E752X_DRB + index, &value);
pci_read_config_byte(pdev, E752X_DRB + index, &value);
/* convert a 128 or 64 MiB DRB to a page size. */
cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
......@@ -904,8 +906,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
u8 row = 0;
for (index = 0; index < 8; index += 2) {
pci_read_config_byte(mci->pdev, E752X_DRB + index,
&value);
pci_read_config_byte(pdev, E752X_DRB + index, &value);
/* test if there is a dimm in this slot */
if (value == last) {
......@@ -918,7 +919,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
last = value;
/* test the next value to see if the dimm is
double sided */
pci_read_config_byte(mci->pdev,
pci_read_config_byte(pdev,
E752X_DRB + index + 1,
&value);
pvt->map[index + 1] = (value == last) ?
......@@ -935,18 +936,18 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
}
/* set the map type. 1 = normal, 0 = reversed */
pci_read_config_byte(mci->pdev, E752X_DRM, &stat8);
pci_read_config_byte(pdev, E752X_DRM, &stat8);
pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f));
mci->edac_cap |= EDAC_FLAG_NONE;
debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
/* load the top of low memory, remap base, and remap limit vars */
pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data);
pci_read_config_word(pdev, E752X_TOLM, &pci_data);
pvt->tolm = ((u32) pci_data) << 4;
pci_read_config_word(mci->pdev, E752X_REMAPBASE, &pci_data);
pci_read_config_word(pdev, E752X_REMAPBASE, &pci_data);
pvt->remapbase = ((u32) pci_data) << 14;
pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data);
pci_read_config_word(pdev, E752X_REMAPLIMIT, &pci_data);
pvt->remaplimit = ((u32) pci_data) << 14;
e752x_printk(KERN_INFO,
"tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
......@@ -1015,7 +1016,7 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev)
debugf0("%s()\n", __func__);
if ((mci = edac_mc_del_mc(pdev)) == NULL)
if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
return;
pvt = (struct e752x_pvt *) mci->pvt_info;
......
......@@ -30,6 +30,8 @@
#include <linux/slab.h>
#include "edac_mc.h"
#define E7XXX_REVISION " Ver: 2.0.0 " __DATE__
#define e7xxx_printk(level, fmt, arg...) \
edac_printk(level, "e7xxx", fmt, ##arg)
......@@ -373,8 +375,8 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
EDAC_FLAG_S4ECD4ED;
/* FIXME - what if different memory types are in different csrows? */
mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.5.2.9 $";
mci->pdev = pdev;
mci->mod_ver = E7XXX_REVISION;
mci->dev = &pdev->dev;
debugf3("%s(): init pvt\n", __func__);
pvt = (struct e7xxx_pvt *) mci->pvt_info;
......@@ -411,7 +413,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
int mem_dev = (dra >> (index * 4 + 3)) & 0x1;
struct csrow_info *csrow = &mci->csrows[index];
pci_read_config_byte(mci->pdev, E7XXX_DRB + index, &value);
pci_read_config_byte(pdev, E7XXX_DRB + index, &value);
/* convert a 64 or 32 MiB DRB to a page size. */
cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
......@@ -448,11 +450,11 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
/* load the top of low memory, remap base, and remap limit vars */
pci_read_config_word(mci->pdev, E7XXX_TOLM, &pci_data);
pci_read_config_word(pdev, E7XXX_TOLM, &pci_data);
pvt->tolm = ((u32) pci_data) << 4;
pci_read_config_word(mci->pdev, E7XXX_REMAPBASE, &pci_data);
pci_read_config_word(pdev, E7XXX_REMAPBASE, &pci_data);
pvt->remapbase = ((u32) pci_data) << 14;
pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data);
pci_read_config_word(pdev, E7XXX_REMAPLIMIT, &pci_data);
pvt->remaplimit = ((u32) pci_data) << 14;
e7xxx_printk(KERN_INFO,
"tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
......@@ -498,7 +500,7 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
debugf0("%s()\n", __func__);
if ((mci = edac_mc_del_mc(pdev)) == NULL)
if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
return;
pvt = (struct e7xxx_pvt *) mci->pvt_info;
......
......@@ -54,16 +54,17 @@ static int log_ce = 1;
static int panic_on_ue;
static int poll_msec = 1000;
static int check_pci_parity = 0; /* default YES check PCI parity */
static int panic_on_pci_parity; /* default no panic on PCI Parity */
static atomic_t pci_parity_count = ATOMIC_INIT(0);
/* lock to memory controller's control array */
static DECLARE_MUTEX(mem_ctls_mutex);
static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
static struct task_struct *edac_thread;
#ifdef CONFIG_PCI
static int check_pci_parity = 0; /* default YES check PCI parity */
static int panic_on_pci_parity; /* default no panic on PCI Parity */
static atomic_t pci_parity_count = ATOMIC_INIT(0);
/* Structure of the whitelist and blacklist arrays */
struct edac_pci_device_list {
unsigned int vendor; /* Vendor ID */
......@@ -80,6 +81,12 @@ static int pci_blacklist_count;
static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES];
static int pci_whitelist_count ;
#ifndef DISABLE_EDAC_SYSFS
static struct kobject edac_pci_kobj; /* /sys/devices/system/edac/pci */
static struct completion edac_pci_kobj_complete;
#endif /* DISABLE_EDAC_SYSFS */
#endif /* CONFIG_PCI */
/* START sysfs data and methods */
#ifndef DISABLE_EDAC_SYSFS
......@@ -127,18 +134,15 @@ static struct sysdev_class edac_class = {
set_kset_name("edac"),
};
/* sysfs objects:
/* sysfs object:
* /sys/devices/system/edac/mc
* /sys/devices/system/edac/pci
*/
static struct kobject edac_memctrl_kobj;
static struct kobject edac_pci_kobj;
/* We use these to wait for the reference counts on edac_memctrl_kobj and
* edac_pci_kobj to reach 0.
*/
static struct completion edac_memctrl_kobj_complete;
static struct completion edac_pci_kobj_complete;
/*
* /sys/devices/system/edac/mc;
......@@ -324,6 +328,8 @@ static void edac_sysfs_memctrl_teardown(void)
#endif /* DISABLE_EDAC_SYSFS */
}
#ifdef CONFIG_PCI
#ifndef DISABLE_EDAC_SYSFS
/*
......@@ -624,6 +630,252 @@ static void edac_sysfs_pci_teardown(void)
#endif
}
static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
{
int where;
u16 status;
where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
pci_read_config_word(dev, where, &status);
/* If we get back 0xFFFF then we must suspect that the card has been
* pulled but the Linux PCI layer has not yet finished cleaning up.
* We don't want to report on such devices
*/
if (status == 0xFFFF) {
u32 sanity;
pci_read_config_dword(dev, 0, &sanity);
if (sanity == 0xFFFFFFFF)
return 0;
}
status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
PCI_STATUS_PARITY;
if (status)
/* reset only the bits we are interested in */
pci_write_config_word(dev, where, status);
return status;
}
typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
/* Clear any PCI parity errors logged by this device. */
static void edac_pci_dev_parity_clear(struct pci_dev *dev)
{
u8 header_type;
get_pci_parity_status(dev, 0);
/* read the device TYPE, looking for bridges */
pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE)
get_pci_parity_status(dev, 1);
}
/*
* PCI Parity polling
*
*/
static void edac_pci_dev_parity_test(struct pci_dev *dev)
{
u16 status;
u8 header_type;
/* read the STATUS register on this device
*/
status = get_pci_parity_status(dev, 0);
debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id );
/* check the status reg for errors */
if (status) {
if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
edac_printk(KERN_CRIT, EDAC_PCI,
"Signaled System Error on %s\n",
pci_name(dev));
if (status & (PCI_STATUS_PARITY)) {
edac_printk(KERN_CRIT, EDAC_PCI,
"Master Data Parity Error on %s\n",
pci_name(dev));
atomic_inc(&pci_parity_count);
}
if (status & (PCI_STATUS_DETECTED_PARITY)) {
edac_printk(KERN_CRIT, EDAC_PCI,
"Detected Parity Error on %s\n",
pci_name(dev));
atomic_inc(&pci_parity_count);
}
}
/* read the device TYPE, looking for bridges */
pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id );
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
/* On bridges, need to examine secondary status register */
status = get_pci_parity_status(dev, 1);
debugf2("PCI SEC_STATUS= 0x%04x %s\n",
status, dev->dev.bus_id );
/* check the secondary status reg for errors */
if (status) {
if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
"Signaled System Error on %s\n",
pci_name(dev));
if (status & (PCI_STATUS_PARITY)) {
edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
"Master Data Parity Error on "
"%s\n", pci_name(dev));
atomic_inc(&pci_parity_count);
}
if (status & (PCI_STATUS_DETECTED_PARITY)) {
edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
"Detected Parity Error on %s\n",
pci_name(dev));
atomic_inc(&pci_parity_count);
}
}
}
}
/*
* check_dev_on_list: Scan for a PCI device on a white/black list
* @list: an EDAC &edac_pci_device_list white/black list pointer
* @free_index: index of next free entry on the list
* @pci_dev: PCI Device pointer
*
* see if list contains the device.
*
* Returns: 0 not found
* 1 found on list
*/
static int check_dev_on_list(struct edac_pci_device_list *list,
int free_index, struct pci_dev *dev)
{
int i;
int rc = 0; /* Assume not found */
unsigned short vendor=dev->vendor;
unsigned short device=dev->device;
/* Scan the list, looking for a vendor/device match */
for (i = 0; i < free_index; i++, list++ ) {
if ((list->vendor == vendor ) && (list->device == device )) {
rc = 1;
break;
}
}
return rc;
}
/*
* pci_dev parity list iterator
* Scan the PCI device list for one iteration, looking for SERRORs
* Master Parity ERRORS or Parity ERRORs on primary or secondary devices
*/
static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
{
struct pci_dev *dev = NULL;
/* request for kernel access to the next PCI device, if any,
* and while we are looking at it have its reference count
* bumped until we are done with it
*/
while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
/* if whitelist exists then it has priority, so only scan
* those devices on the whitelist
*/
if (pci_whitelist_count > 0 ) {
if (check_dev_on_list(pci_whitelist,
pci_whitelist_count, dev))
fn(dev);
} else {
/*
* if no whitelist, then check if this devices is
* blacklisted
*/
if (!check_dev_on_list(pci_blacklist,
pci_blacklist_count, dev))
fn(dev);
}
}
}
static void do_pci_parity_check(void)
{
unsigned long flags;
int before_count;
debugf3("%s()\n", __func__);
if (!check_pci_parity)
return;
before_count = atomic_read(&pci_parity_count);
/* scan all PCI devices looking for a Parity Error on devices and
* bridges
*/
local_irq_save(flags);
edac_pci_dev_parity_iterator(edac_pci_dev_parity_test);
local_irq_restore(flags);
/* Only if operator has selected panic on PCI Error */
if (panic_on_pci_parity) {
/* If the count is different 'after' from 'before' */
if (before_count != atomic_read(&pci_parity_count))
panic("EDAC: PCI Parity Error");
}
}
static inline void clear_pci_parity_errors(void)
{
/* Clear any PCI bus parity errors that devices initially have logged
* in their registers.
*/
edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
}
#else /* CONFIG_PCI */
static inline void do_pci_parity_check(void)
{
/* no-op */
}
static inline void clear_pci_parity_errors(void)
{
/* no-op */
}
static void edac_sysfs_pci_teardown(void)
{
}
static int edac_sysfs_pci_setup(void)
{
return 0;
}
#endif /* CONFIG_PCI */
#ifndef DISABLE_EDAC_SYSFS
/* EDAC sysfs CSROW data structures and methods */
......@@ -1132,7 +1384,7 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
return err;
/* create a symlink for the device */
err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj,
err = sysfs_create_link(edac_mci_kobj, &mci->dev->kobj,
EDAC_DEVICE_SYMLINK);
if (err)
......@@ -1238,7 +1490,7 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci)
debugf4("\tmci->edac_check = %p\n", mci->edac_check);
debugf3("\tmci->nr_csrows = %d, csrows = %p\n",
mci->nr_csrows, mci->csrows);
debugf3("\tpdev = %p\n", mci->pdev);
debugf3("\tdev = %p\n", mci->dev);
debugf3("\tmod_name:ctl_name = %s:%s\n",
mci->mod_name, mci->ctl_name);
debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
......@@ -1363,7 +1615,7 @@ void edac_mc_free(struct mem_ctl_info *mci)
}
EXPORT_SYMBOL_GPL(edac_mc_free);
static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev)
static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
{
struct mem_ctl_info *mci;
struct list_head *item;
......@@ -1373,7 +1625,7 @@ static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev)
list_for_each(item, &mc_devices) {
mci = list_entry(item, struct mem_ctl_info, link);
if (mci->pdev == pdev)
if (mci->dev == dev)
return mci;
}
......@@ -1390,12 +1642,12 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci)
mci->mc_idx = 0;
insert_before = &mc_devices;
} else {
if (find_mci_by_pdev(mci->pdev)) {
if (find_mci_by_dev(mci->dev)) {
edac_printk(KERN_WARNING, EDAC_MC,
"%s (%s) %s %s already assigned %d\n",
mci->pdev->dev.bus_id,
pci_name(mci->pdev), mci->mod_name,
mci->ctl_name, mci->mc_idx);
mci->dev->bus_id, dev_name(mci->dev),
mci->mod_name, mci->ctl_name,
mci->mc_idx);
return 1;
}
......@@ -1486,8 +1738,8 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
}
/* Report action taken */
edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: PCI %s\n",
mci->mod_name, mci->ctl_name, pci_name(mci->pdev));
edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n",
mci->mod_name, mci->ctl_name, dev_name(mci->dev));
up(&mem_ctls_mutex);
return 0;
......@@ -1504,18 +1756,18 @@ EXPORT_SYMBOL_GPL(edac_mc_add_mc);
/**
* edac_mc_del_mc: Remove sysfs entries for specified mci structure and
* remove mci structure from global list
* @pdev: Pointer to 'struct pci_dev' representing mci structure to remove.
* @pdev: Pointer to 'struct device' representing mci structure to remove.
*
* Return pointer to removed mci structure, or NULL if device not found.
*/
struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev)
struct mem_ctl_info * edac_mc_del_mc(struct device *dev)
{
struct mem_ctl_info *mci;
debugf0("MC: %s()\n", __func__);
down(&mem_ctls_mutex);
if ((mci = find_mci_by_pdev(pdev)) == NULL) {
if ((mci = find_mci_by_dev(dev)) == NULL) {
up(&mem_ctls_mutex);
return NULL;
}
......@@ -1524,8 +1776,8 @@ struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev)
del_mc_from_global_list(mci);
up(&mem_ctls_mutex);
edac_printk(KERN_INFO, EDAC_MC,
"Removed device %d for %s %s: PCI %s\n", mci->mc_idx,
mci->mod_name, mci->ctl_name, pci_name(mci->pdev));
"Removed device %d for %s %s: DEV %s\n", mci->mc_idx,
mci->mod_name, mci->ctl_name, dev_name(mci->dev));
return mci;
}
EXPORT_SYMBOL_GPL(edac_mc_del_mc);
......@@ -1739,244 +1991,6 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
}
EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info);
#ifdef CONFIG_PCI
static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
{
int where;
u16 status;
where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
pci_read_config_word(dev, where, &status);