mirror of https://gitee.com/openkylin/linux.git
* hide EDAC workqueue from users (Borislav Petkov)
* edac_subsys init/teardown cleanup (Borislav Petkov) * make mpc85xx-pci-edac a platform device (Scott Wood) * sb_edac KNL gen2 support (Jim Snow) * other small cleanups all over the place -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWk2YzAAoJEBLB8Bhh3lVKzeAQAJ2XHbErMLzqIiFHpLCcCGTP 49pjv/i2C1+lVcGld4ddFcyGei5TU4h/+TqaI2QxrheN8kLjmFpaT+kb8v4nT09+ oW9cMa3DiY79cNdRmYegaJfkEk+CLu9JEHrFw5by8RShy83LliN/HsvQ9bupxL93 5TMvVOEWdtxcEA5y7/7YCVfvRbjEmQFJJByZjyXTOxTXXpqDdRy0mleDAaIa7c35 o3HbR3DXm5YL0Nb0gul5IkCgzhBfAzMXS2vaOK4Jnqlbn9kjE6NtP1Ks6NNFSLQ+ xd189BQwqOuQnMqczwnskaWhxySTlP36DUlomJKgr3IePveUnhTg0mtYMHluYPZe rnXykwF+CLHNztPsYya1u3y3xiYR1jnHy3UHUxygOJxqOFocfniBTFf3Q/Kd36DX 9bFWTpuBn+grjiIXnZYtzALOnj+I9BZLFsUARSv1PrbBMcXDwGfkjNWmnQHqQyQ0 Nbgs9+h+b17mG8kSbrYBYGmgxp1lmiZ+B7CUb1jOEjgPyD8ypNeaZUY2Hf+Sh+26 1cF8HSaGc7oEcfJGqKqeg6AYnxMl3FQBFKsy2bnX9IsdTihqKOAxYqih409/cj9r HwQSn0ipFDXFq/dns3icwtvBSzIAK8BjKRyCtnD5KOvKzZuoRgEB2Wyhq3yFY34q ON6y6wDmIveCRpEvqFKN =9d1r -----END PGP SIGNATURE----- Merge tag 'edac_for_4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp Pull EDAC updates from Borislav Petkov: - hide EDAC workqueue from users (Borislav Petkov) - edac_subsys init/teardown cleanup (Borislav Petkov) - make mpc85xx-pci-edac a platform device (Scott Wood) - sb_edac KNL gen2 support (Jim Snow) - other small cleanups all over the place * tag 'edac_for_4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp: EDAC, i5100: Use to_delayed_work() MAINTAINERS: Fix EDAC repo URLs format EDAC, sb_edac: Set fixed DIMM width on Xeon Knights Landing EDAC: Rework workqueue handling EDAC: Make edac_device workqueue setup/teardown functions static EDAC: Remove edac_get_sysfs_subsys() error handling EDAC: Unexport and make edac_subsys static EDAC: Rip out the edac_subsys reference counting EDAC: Robustify workqueues destruction EDAC, mc_sysfs: Fix freeing bus' name EDAC, mpc85xx: Make mpc85xx-pci-edac a platform device EDAC, sb_edac: Add Knights Landing (Xeon Phi gen 2) support EDAC, sb_edac: Add support for duplicate device IDs EDAC, sb_edac: Virtualize several hard-coded functions EDAC, mv64x60: Use platform_register/unregister_drivers() EDAC, mpc85xx: Use platform_register/unregister_drivers() EDAC: Add DDR4 flag EDAC: Remove references to bluesmoke.sourceforge.net EDAC, pci: Remove old disabled code
This commit is contained in:
commit
d870a9d5e3
|
@ -1,9 +1,13 @@
|
|||
EDAC - Error Detection And Correction
|
||||
=====================================
|
||||
|
||||
"bluesmoke" was the name for this device driver when it was "out-of-tree"
|
||||
and maintained at sourceforge.net. When it was pushed into 2.6.16 for the
|
||||
first time, it was renamed to 'EDAC'.
|
||||
"bluesmoke" was the name for this device driver when it
|
||||
was "out-of-tree" and maintained at sourceforge.net -
|
||||
bluesmoke.sourceforge.net. That site is mostly archaic now and can be
|
||||
used only for historical purposes.
|
||||
|
||||
When the subsystem was pushed into 2.6.16 for the first time, it was
|
||||
renamed to 'EDAC'.
|
||||
|
||||
PURPOSE
|
||||
-------
|
||||
|
|
23
MAINTAINERS
23
MAINTAINERS
|
@ -3933,9 +3933,8 @@ M: Doug Thompson <dougthompson@xmission.com>
|
|||
M: Borislav Petkov <bp@alien8.de>
|
||||
M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
T: git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git#for-next
|
||||
T: git://git.kernel.org/pub/linux/kernel/git/mchehab/linux-edac.git#linux_next
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git for-next
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git linux_next
|
||||
S: Supported
|
||||
F: Documentation/edac.txt
|
||||
F: drivers/edac/
|
||||
|
@ -3945,7 +3944,6 @@ EDAC-AMD64
|
|||
M: Doug Thompson <dougthompson@xmission.com>
|
||||
M: Borislav Petkov <bp@alien8.de>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/amd64_edac*
|
||||
|
||||
|
@ -3953,7 +3951,6 @@ EDAC-CALXEDA
|
|||
M: Doug Thompson <dougthompson@xmission.com>
|
||||
M: Robert Richter <rric@kernel.org>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/highbank*
|
||||
|
||||
|
@ -3962,7 +3959,6 @@ M: Ralf Baechle <ralf@linux-mips.org>
|
|||
M: David Daney <david.daney@cavium.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
L: linux-mips@linux-mips.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Supported
|
||||
F: drivers/edac/octeon_edac*
|
||||
|
||||
|
@ -3970,63 +3966,54 @@ EDAC-E752X
|
|||
M: Mark Gross <mark.gross@intel.com>
|
||||
M: Doug Thompson <dougthompson@xmission.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/e752x_edac.c
|
||||
|
||||
EDAC-E7XXX
|
||||
M: Doug Thompson <dougthompson@xmission.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/e7xxx_edac.c
|
||||
|
||||
EDAC-GHES
|
||||
M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/ghes_edac.c
|
||||
|
||||
EDAC-I82443BXGX
|
||||
M: Tim Small <tim@buttersideup.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/i82443bxgx_edac.c
|
||||
|
||||
EDAC-I3000
|
||||
M: Jason Uhlenkott <juhlenko@akamai.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/i3000_edac.c
|
||||
|
||||
EDAC-I5000
|
||||
M: Doug Thompson <dougthompson@xmission.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/i5000_edac.c
|
||||
|
||||
EDAC-I5400
|
||||
M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/i5400_edac.c
|
||||
|
||||
EDAC-I7300
|
||||
M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/i7300_edac.c
|
||||
|
||||
EDAC-I7CORE
|
||||
M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/i7core_edac.c
|
||||
|
||||
|
@ -4034,42 +4021,36 @@ EDAC-I82975X
|
|||
M: Ranganathan Desikan <ravi@jetztechnologies.com>
|
||||
M: "Arvind R." <arvino55@gmail.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/i82975x_edac.c
|
||||
|
||||
EDAC-IE31200
|
||||
M: Jason Baron <jbaron@akamai.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/ie31200_edac.c
|
||||
|
||||
EDAC-MPC85XX
|
||||
M: Johannes Thumshirn <morbidrsa@gmail.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/mpc85xx_edac.[ch]
|
||||
|
||||
EDAC-PASEMI
|
||||
M: Egor Martovetsky <egor@pasemi.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/pasemi_edac.c
|
||||
|
||||
EDAC-R82600
|
||||
M: Tim Small <tim@buttersideup.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/r82600_edac.c
|
||||
|
||||
EDAC-SBRIDGE
|
||||
M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
||||
L: linux-edac@vger.kernel.org
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/edac/sb_edac.c
|
||||
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/fsl/edac.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
@ -1255,6 +1257,25 @@ void fsl_pcibios_fixup_phb(struct pci_controller *phb)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int add_err_dev(struct platform_device *pdev)
|
||||
{
|
||||
struct platform_device *errdev;
|
||||
struct mpc85xx_edac_pci_plat_data pd = {
|
||||
.of_node = pdev->dev.of_node
|
||||
};
|
||||
|
||||
errdev = platform_device_register_resndata(&pdev->dev,
|
||||
"mpc85xx-pci-edac",
|
||||
PLATFORM_DEVID_AUTO,
|
||||
pdev->resource,
|
||||
pdev->num_resources,
|
||||
&pd, sizeof(pd));
|
||||
if (IS_ERR(errdev))
|
||||
return PTR_ERR(errdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsl_pci_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
@ -1262,8 +1283,13 @@ static int fsl_pci_probe(struct platform_device *pdev)
|
|||
|
||||
node = pdev->dev.of_node;
|
||||
ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mpc85xx_pci_err_probe(pdev);
|
||||
ret = add_err_dev(pdev);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "couldn't register error device: %d\n",
|
||||
ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -130,15 +130,6 @@ void fsl_pci_assign_primary(void);
|
|||
static inline void fsl_pci_assign_primary(void) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EDAC_MPC85XX
|
||||
int mpc85xx_pci_err_probe(struct platform_device *op);
|
||||
#else
|
||||
static inline int mpc85xx_pci_err_probe(struct platform_device *op)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_PCI
|
||||
extern int fsl_pci_mcheck_exception(struct pt_regs *);
|
||||
#else
|
||||
|
|
|
@ -10,7 +10,7 @@ obj-$(CONFIG_EDAC) := edac_stub.o
|
|||
obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
|
||||
|
||||
edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o
|
||||
edac_core-y += edac_module.o edac_device_sysfs.o
|
||||
edac_core-y += edac_module.o edac_device_sysfs.o wq.o
|
||||
|
||||
edac_core-$(CONFIG_EDAC_DEBUG) += debugfs.o
|
||||
|
||||
|
|
|
@ -390,11 +390,9 @@ static void edac_device_workq_function(struct work_struct *work_req)
|
|||
* between integral seconds
|
||||
*/
|
||||
if (edac_dev->poll_msec == 1000)
|
||||
queue_delayed_work(edac_workqueue, &edac_dev->work,
|
||||
round_jiffies_relative(edac_dev->delay));
|
||||
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
||||
else
|
||||
queue_delayed_work(edac_workqueue, &edac_dev->work,
|
||||
edac_dev->delay);
|
||||
edac_queue_work(&edac_dev->work, edac_dev->delay);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -402,8 +400,8 @@ static void edac_device_workq_function(struct work_struct *work_req)
|
|||
* initialize a workq item for this edac_device instance
|
||||
* passing in the new delay period in msec
|
||||
*/
|
||||
void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
|
||||
unsigned msec)
|
||||
static void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
|
||||
unsigned msec)
|
||||
{
|
||||
edac_dbg(0, "\n");
|
||||
|
||||
|
@ -422,29 +420,23 @@ void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
|
|||
* to fire together on the 1 second exactly
|
||||
*/
|
||||
if (edac_dev->poll_msec == 1000)
|
||||
queue_delayed_work(edac_workqueue, &edac_dev->work,
|
||||
round_jiffies_relative(edac_dev->delay));
|
||||
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
||||
else
|
||||
queue_delayed_work(edac_workqueue, &edac_dev->work,
|
||||
edac_dev->delay);
|
||||
edac_queue_work(&edac_dev->work, edac_dev->delay);
|
||||
}
|
||||
|
||||
/*
|
||||
* edac_device_workq_teardown
|
||||
* stop the workq processing on this edac_dev
|
||||
*/
|
||||
void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
|
||||
static void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!edac_dev->edac_check)
|
||||
return;
|
||||
|
||||
status = cancel_delayed_work(&edac_dev->work);
|
||||
if (status == 0) {
|
||||
/* workq instance might be running, wait for it */
|
||||
flush_workqueue(edac_workqueue);
|
||||
}
|
||||
edac_dev->op_state = OP_OFFLINE;
|
||||
|
||||
edac_stop_work(&edac_dev->work);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -457,16 +449,15 @@ void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
|
|||
void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
|
||||
unsigned long value)
|
||||
{
|
||||
/* cancel the current workq request, without the mutex lock */
|
||||
edac_device_workq_teardown(edac_dev);
|
||||
unsigned long jiffs = msecs_to_jiffies(value);
|
||||
|
||||
/* acquire the mutex before doing the workq setup */
|
||||
mutex_lock(&device_ctls_mutex);
|
||||
if (value == 1000)
|
||||
jiffs = round_jiffies_relative(value);
|
||||
|
||||
/* restart the workq request, with new delay value */
|
||||
edac_device_workq_setup(edac_dev, value);
|
||||
edac_dev->poll_msec = value;
|
||||
edac_dev->delay = jiffs;
|
||||
|
||||
mutex_unlock(&device_ctls_mutex);
|
||||
edac_mod_work(&edac_dev->work, jiffs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -237,11 +237,6 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
|
|||
|
||||
/* get the /sys/devices/system/edac reference */
|
||||
edac_subsys = edac_get_sysfs_subsys();
|
||||
if (edac_subsys == NULL) {
|
||||
edac_dbg(1, "no edac_subsys error\n");
|
||||
err = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Point to the 'edac_subsys' this instance 'reports' to */
|
||||
edac_dev->edac_subsys = edac_subsys;
|
||||
|
@ -256,7 +251,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
|
|||
|
||||
if (!try_module_get(edac_dev->owner)) {
|
||||
err = -ENODEV;
|
||||
goto err_mod_get;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* register */
|
||||
|
@ -282,9 +277,6 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
|
|||
err_kobj_reg:
|
||||
module_put(edac_dev->owner);
|
||||
|
||||
err_mod_get:
|
||||
edac_put_sysfs_subsys();
|
||||
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
@ -306,7 +298,6 @@ void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
|
|||
* b) 'kfree' the memory
|
||||
*/
|
||||
kobject_put(&dev->kobj);
|
||||
edac_put_sysfs_subsys();
|
||||
}
|
||||
|
||||
/* edac_dev -> instance information */
|
||||
|
|
|
@ -548,8 +548,7 @@ static void edac_mc_workq_function(struct work_struct *work_req)
|
|||
mutex_unlock(&mem_ctls_mutex);
|
||||
|
||||
/* Reschedule */
|
||||
queue_delayed_work(edac_workqueue, &mci->work,
|
||||
msecs_to_jiffies(edac_mc_get_poll_msec()));
|
||||
edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec()));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -561,8 +560,7 @@ static void edac_mc_workq_function(struct work_struct *work_req)
|
|||
*
|
||||
* called with the mem_ctls_mutex held
|
||||
*/
|
||||
static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
|
||||
bool init)
|
||||
static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
|
||||
{
|
||||
edac_dbg(0, "\n");
|
||||
|
||||
|
@ -570,10 +568,9 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
|
|||
if (mci->op_state != OP_RUNNING_POLL)
|
||||
return;
|
||||
|
||||
if (init)
|
||||
INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
|
||||
INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
|
||||
|
||||
mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
|
||||
edac_queue_work(&mci->work, msecs_to_jiffies(msec));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -586,18 +583,9 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
|
|||
*/
|
||||
static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
|
||||
{
|
||||
int status;
|
||||
mci->op_state = OP_OFFLINE;
|
||||
|
||||
if (mci->op_state != OP_RUNNING_POLL)
|
||||
return;
|
||||
|
||||
status = cancel_delayed_work(&mci->work);
|
||||
if (status == 0) {
|
||||
edac_dbg(0, "not canceled, flush the queue\n");
|
||||
|
||||
/* workq instance might be running, wait for it */
|
||||
flush_workqueue(edac_workqueue);
|
||||
}
|
||||
edac_stop_work(&mci->work);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -616,9 +604,8 @@ void edac_mc_reset_delay_period(unsigned long value)
|
|||
list_for_each(item, &mc_devices) {
|
||||
mci = list_entry(item, struct mem_ctl_info, link);
|
||||
|
||||
edac_mc_workq_setup(mci, value, false);
|
||||
edac_mod_work(&mci->work, value);
|
||||
}
|
||||
|
||||
mutex_unlock(&mem_ctls_mutex);
|
||||
}
|
||||
|
||||
|
@ -789,7 +776,7 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
|
|||
/* This instance is NOW RUNNING */
|
||||
mci->op_state = OP_RUNNING_POLL;
|
||||
|
||||
edac_mc_workq_setup(mci, edac_mc_get_poll_msec(), true);
|
||||
edac_mc_workq_setup(mci, edac_mc_get_poll_msec());
|
||||
} else {
|
||||
mci->op_state = OP_RUNNING_INTERRUPT;
|
||||
}
|
||||
|
|
|
@ -880,21 +880,26 @@ static struct device_type mci_attr_type = {
|
|||
int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
char *name;
|
||||
int i, err;
|
||||
|
||||
/*
|
||||
* The memory controller needs its own bus, in order to avoid
|
||||
* namespace conflicts at /sys/bus/edac.
|
||||
*/
|
||||
mci->bus->name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
|
||||
if (!mci->bus->name)
|
||||
name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
mci->bus->name = name;
|
||||
|
||||
edac_dbg(0, "creating bus %s\n", mci->bus->name);
|
||||
|
||||
err = bus_register(mci->bus);
|
||||
if (err < 0)
|
||||
goto fail_free_name;
|
||||
if (err < 0) {
|
||||
kfree(name);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* get the /sys/devices/system/edac subsys reference */
|
||||
mci->dev.type = &mci_attr_type;
|
||||
|
@ -961,8 +966,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
|
|||
device_unregister(&mci->dev);
|
||||
fail_unregister_bus:
|
||||
bus_unregister(mci->bus);
|
||||
fail_free_name:
|
||||
kfree(mci->bus->name);
|
||||
kfree(name);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -993,10 +998,12 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
|
|||
|
||||
void edac_unregister_sysfs(struct mem_ctl_info *mci)
|
||||
{
|
||||
const char *name = mci->bus->name;
|
||||
|
||||
edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));
|
||||
device_unregister(&mci->dev);
|
||||
bus_unregister(mci->bus);
|
||||
kfree(mci->bus->name);
|
||||
kfree(name);
|
||||
}
|
||||
|
||||
static void mc_attr_release(struct device *dev)
|
||||
|
@ -1018,24 +1025,15 @@ static struct device_type mc_attr_type = {
|
|||
*/
|
||||
int __init edac_mc_sysfs_init(void)
|
||||
{
|
||||
struct bus_type *edac_subsys;
|
||||
int err;
|
||||
|
||||
/* get the /sys/devices/system/edac subsys reference */
|
||||
edac_subsys = edac_get_sysfs_subsys();
|
||||
if (edac_subsys == NULL) {
|
||||
edac_dbg(1, "no edac_subsys\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL);
|
||||
if (!mci_pdev) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_sysfs;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mci_pdev->bus = edac_subsys;
|
||||
mci_pdev->bus = edac_get_sysfs_subsys();
|
||||
mci_pdev->type = &mc_attr_type;
|
||||
device_initialize(mci_pdev);
|
||||
dev_set_name(mci_pdev, "mc");
|
||||
|
@ -1050,8 +1048,6 @@ int __init edac_mc_sysfs_init(void)
|
|||
|
||||
out_dev_free:
|
||||
kfree(mci_pdev);
|
||||
out_put_sysfs:
|
||||
edac_put_sysfs_subsys();
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -1059,5 +1055,4 @@ int __init edac_mc_sysfs_init(void)
|
|||
void edac_mc_sysfs_exit(void)
|
||||
{
|
||||
device_unregister(mci_pdev);
|
||||
edac_put_sysfs_subsys();
|
||||
}
|
||||
|
|
|
@ -43,9 +43,6 @@ module_param_call(edac_debug_level, edac_set_debug_level, param_get_int,
|
|||
MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
|
||||
#endif
|
||||
|
||||
/* scope is to module level only */
|
||||
struct workqueue_struct *edac_workqueue;
|
||||
|
||||
/*
|
||||
* edac_op_state_to_string()
|
||||
*/
|
||||
|
@ -66,31 +63,37 @@ char *edac_op_state_to_string(int opstate)
|
|||
}
|
||||
|
||||
/*
|
||||
* edac_workqueue_setup
|
||||
* initialize the edac work queue for polling operations
|
||||
* sysfs object: /sys/devices/system/edac
|
||||
* need to export to other files
|
||||
*/
|
||||
static int edac_workqueue_setup(void)
|
||||
static struct bus_type edac_subsys = {
|
||||
.name = "edac",
|
||||
.dev_name = "edac",
|
||||
};
|
||||
|
||||
static int edac_subsys_init(void)
|
||||
{
|
||||
edac_workqueue = create_singlethread_workqueue("edac-poller");
|
||||
if (edac_workqueue == NULL)
|
||||
return -ENODEV;
|
||||
else
|
||||
return 0;
|
||||
int err;
|
||||
|
||||
/* create the /sys/devices/system/edac directory */
|
||||
err = subsys_system_register(&edac_subsys, NULL);
|
||||
if (err)
|
||||
printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* edac_workqueue_teardown
|
||||
* teardown the edac workqueue
|
||||
*/
|
||||
static void edac_workqueue_teardown(void)
|
||||
static void edac_subsys_exit(void)
|
||||
{
|
||||
if (edac_workqueue) {
|
||||
flush_workqueue(edac_workqueue);
|
||||
destroy_workqueue(edac_workqueue);
|
||||
edac_workqueue = NULL;
|
||||
}
|
||||
bus_unregister(&edac_subsys);
|
||||
}
|
||||
|
||||
/* return pointer to the 'edac' node in sysfs */
|
||||
struct bus_type *edac_get_sysfs_subsys(void)
|
||||
{
|
||||
return &edac_subsys;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(edac_get_sysfs_subsys);
|
||||
/*
|
||||
* edac_init
|
||||
* module initialization entry point
|
||||
|
@ -101,6 +104,10 @@ static int __init edac_init(void)
|
|||
|
||||
edac_printk(KERN_INFO, EDAC_MC, EDAC_VERSION "\n");
|
||||
|
||||
err = edac_subsys_init();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Harvest and clear any boot/initialization PCI parity errors
|
||||
*
|
||||
|
@ -129,6 +136,8 @@ static int __init edac_init(void)
|
|||
edac_mc_sysfs_exit();
|
||||
|
||||
err_sysfs:
|
||||
edac_subsys_exit();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -144,6 +153,7 @@ static void __exit edac_exit(void)
|
|||
edac_workqueue_teardown();
|
||||
edac_mc_sysfs_exit();
|
||||
edac_debugfs_exit();
|
||||
edac_subsys_exit();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -47,10 +47,12 @@ extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev);
|
|||
extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev);
|
||||
|
||||
/* edac core workqueue: single CPU mode */
|
||||
extern struct workqueue_struct *edac_workqueue;
|
||||
extern void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
|
||||
unsigned msec);
|
||||
extern void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev);
|
||||
int edac_workqueue_setup(void);
|
||||
void edac_workqueue_teardown(void);
|
||||
bool edac_queue_work(struct delayed_work *work, unsigned long delay);
|
||||
bool edac_stop_work(struct delayed_work *work);
|
||||
bool edac_mod_work(struct delayed_work *work, unsigned long delay);
|
||||
|
||||
extern void edac_device_reset_delay_period(struct edac_device_ctl_info
|
||||
*edac_dev, unsigned long value);
|
||||
extern void edac_mc_reset_delay_period(unsigned long value);
|
||||
|
|
|
@ -178,41 +178,6 @@ static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci)
|
|||
INIT_LIST_HEAD(&pci->link);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Older code, but might use in the future */
|
||||
|
||||
/*
|
||||
* edac_pci_find()
|
||||
* Search for an edac_pci_ctl_info structure whose index is 'idx'
|
||||
*
|
||||
* If found, return a pointer to the structure
|
||||
* Else return NULL.
|
||||
*
|
||||
* Caller must hold pci_ctls_mutex.
|
||||
*/
|
||||
struct edac_pci_ctl_info *edac_pci_find(int idx)
|
||||
{
|
||||
struct list_head *item;
|
||||
struct edac_pci_ctl_info *pci;
|
||||
|
||||
/* Iterage over list, looking for exact match of ID */
|
||||
list_for_each(item, &edac_pci_list) {
|
||||
pci = list_entry(item, struct edac_pci_ctl_info, link);
|
||||
|
||||
if (pci->pci_idx >= idx) {
|
||||
if (pci->pci_idx == idx)
|
||||
return pci;
|
||||
|
||||
/* not on list, so terminate early */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(edac_pci_find);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* edac_pci_workq_function()
|
||||
*
|
||||
|
@ -244,7 +209,7 @@ static void edac_pci_workq_function(struct work_struct *work_req)
|
|||
delay = msecs_to_jiffies(msec);
|
||||
|
||||
/* Reschedule only if we are in POLL mode */
|
||||
queue_delayed_work(edac_workqueue, &pci->work, delay);
|
||||
edac_queue_work(&pci->work, delay);
|
||||
}
|
||||
|
||||
mutex_unlock(&edac_pci_ctls_mutex);
|
||||
|
@ -264,8 +229,8 @@ static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
|
|||
edac_dbg(0, "\n");
|
||||
|
||||
INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
|
||||
queue_delayed_work(edac_workqueue, &pci->work,
|
||||
msecs_to_jiffies(edac_pci_get_poll_msec()));
|
||||
|
||||
edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec()));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -274,38 +239,13 @@ static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
|
|||
*/
|
||||
static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
|
||||
{
|
||||
int status;
|
||||
|
||||
edac_dbg(0, "\n");
|
||||
|
||||
status = cancel_delayed_work(&pci->work);
|
||||
if (status == 0)
|
||||
flush_workqueue(edac_workqueue);
|
||||
pci->op_state = OP_OFFLINE;
|
||||
|
||||
edac_stop_work(&pci->work);
|
||||
}
|
||||
|
||||
/*
|
||||
* edac_pci_reset_delay_period
|
||||
*
|
||||
* called with a new period value for the workq period
|
||||
* a) stop current workq timer
|
||||
* b) restart workq timer with new value
|
||||
*/
|
||||
void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci,
|
||||
unsigned long value)
|
||||
{
|
||||
edac_dbg(0, "\n");
|
||||
|
||||
edac_pci_workq_teardown(pci);
|
||||
|
||||
/* need to lock for the setup */
|
||||
mutex_lock(&edac_pci_ctls_mutex);
|
||||
|
||||
edac_pci_workq_setup(pci, value);
|
||||
|
||||
mutex_unlock(&edac_pci_ctls_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period);
|
||||
|
||||
/*
|
||||
* edac_pci_alloc_index: Allocate a unique PCI index number
|
||||
*
|
||||
|
|
|
@ -331,10 +331,7 @@ static struct kobj_type ktype_edac_pci_main_kobj = {
|
|||
};
|
||||
|
||||
/**
|
||||
* edac_pci_main_kobj_setup()
|
||||
*
|
||||
* setup the sysfs for EDAC PCI attributes
|
||||
* assumes edac_subsys has already been initialized
|
||||
* edac_pci_main_kobj_setup: Setup the sysfs for EDAC PCI attributes.
|
||||
*/
|
||||
static int edac_pci_main_kobj_setup(void)
|
||||
{
|
||||
|
@ -351,11 +348,6 @@ static int edac_pci_main_kobj_setup(void)
|
|||
* controls and attributes
|
||||
*/
|
||||
edac_subsys = edac_get_sysfs_subsys();
|
||||
if (edac_subsys == NULL) {
|
||||
edac_dbg(1, "no edac_subsys\n");
|
||||
err = -ENODEV;
|
||||
goto decrement_count_fail;
|
||||
}
|
||||
|
||||
/* Bump the reference count on this module to ensure the
|
||||
* modules isn't unloaded until we deconstruct the top
|
||||
|
@ -364,7 +356,7 @@ static int edac_pci_main_kobj_setup(void)
|
|||
if (!try_module_get(THIS_MODULE)) {
|
||||
edac_dbg(1, "try_module_get() failed\n");
|
||||
err = -ENODEV;
|
||||
goto mod_get_fail;
|
||||
goto decrement_count_fail;
|
||||
}
|
||||
|
||||
edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
|
||||
|
@ -399,9 +391,6 @@ static int edac_pci_main_kobj_setup(void)
|
|||
kzalloc_fail:
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
mod_get_fail:
|
||||
edac_put_sysfs_subsys();
|
||||
|
||||
decrement_count_fail:
|
||||
/* if are on this error exit, nothing to tear down */
|
||||
atomic_dec(&edac_pci_sysfs_refcount);
|
||||
|
@ -426,7 +415,6 @@ static void edac_pci_main_kobj_teardown(void)
|
|||
if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
|
||||
edac_dbg(0, "called kobject_put on main kobj\n");
|
||||
kobject_put(edac_pci_top_main_kobj);
|
||||
edac_put_sysfs_subsys();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@ EXPORT_SYMBOL_GPL(edac_handlers);
|
|||
int edac_err_assert = 0;
|
||||
EXPORT_SYMBOL_GPL(edac_err_assert);
|
||||
|
||||
static atomic_t edac_subsys_valid = ATOMIC_INIT(0);
|
||||
|
||||
int edac_report_status = EDAC_REPORTING_ENABLED;
|
||||
EXPORT_SYMBOL_GPL(edac_report_status);
|
||||
|
||||
|
@ -68,42 +66,3 @@ void edac_atomic_assert_error(void)
|
|||
edac_err_assert++;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(edac_atomic_assert_error);
|
||||
|
||||
/*
|
||||
* sysfs object: /sys/devices/system/edac
|
||||
* need to export to other files
|
||||
*/
|
||||
struct bus_type edac_subsys = {
|
||||
.name = "edac",
|
||||
.dev_name = "edac",
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(edac_subsys);
|
||||
|
||||
/* return pointer to the 'edac' node in sysfs */
|
||||
struct bus_type *edac_get_sysfs_subsys(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (atomic_read(&edac_subsys_valid))
|
||||
goto out;
|
||||
|
||||
/* create the /sys/devices/system/edac directory */
|
||||
err = subsys_system_register(&edac_subsys, NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
atomic_inc(&edac_subsys_valid);
|
||||
return &edac_subsys;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(edac_get_sysfs_subsys);
|
||||
|
||||
void edac_put_sysfs_subsys(void)
|
||||
{
|
||||
/* last user unregisters it */
|
||||
if (atomic_dec_and_test(&edac_subsys_valid))
|
||||
bus_unregister(&edac_subsys);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(edac_put_sysfs_subsys);
|
||||
|
|
|
@ -575,9 +575,7 @@ static void i5100_check_error(struct mem_ctl_info *mci)
|
|||
|
||||
static void i5100_refresh_scrubbing(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *i5100_scrubbing = container_of(work,
|
||||
struct delayed_work,
|
||||
work);
|
||||
struct delayed_work *i5100_scrubbing = to_delayed_work(work);
|
||||
struct i5100_priv *priv = container_of(i5100_scrubbing,
|
||||
struct i5100_priv,
|
||||
i5100_scrubbing);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/edac.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/fsl/edac.h>
|
||||
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
|
@ -238,10 +239,12 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int mpc85xx_pci_err_probe(struct platform_device *op)
|
||||
static int mpc85xx_pci_err_probe(struct platform_device *op)
|
||||
{
|
||||
struct edac_pci_ctl_info *pci;
|
||||
struct mpc85xx_pci_pdata *pdata;
|
||||
struct mpc85xx_edac_pci_plat_data *plat_data;
|
||||
struct device_node *of_node;
|
||||
struct resource r;
|
||||
int res = 0;
|
||||
|
||||
|
@ -266,7 +269,15 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
|
|||
pdata->name = "mpc85xx_pci_err";
|
||||
pdata->irq = NO_IRQ;
|
||||
|
||||
if (mpc85xx_pcie_find_capability(op->dev.of_node) > 0)
|
||||
plat_data = op->dev.platform_data;
|
||||
if (!plat_data) {
|
||||
dev_err(&op->dev, "no platform data");
|
||||
res = -ENXIO;
|
||||
goto err;
|
||||
}
|
||||
of_node = plat_data->of_node;
|
||||
|
||||
if (mpc85xx_pcie_find_capability(of_node) > 0)
|
||||
pdata->is_pcie = true;
|
||||
|
||||
dev_set_drvdata(&op->dev, pci);
|
||||
|
@ -284,7 +295,7 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
|
|||
|
||||
pdata->edac_idx = edac_pci_idx++;
|
||||
|
||||
res = of_address_to_resource(op->dev.of_node, 0, &r);
|
||||
res = of_address_to_resource(of_node, 0, &r);
|
||||
if (res) {
|
||||
printk(KERN_ERR "%s: Unable to get resource for "
|
||||
"PCI err regs\n", __func__);
|
||||
|
@ -339,7 +350,7 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
|
|||
}
|
||||
|
||||
if (edac_op_state == EDAC_OPSTATE_INT) {
|
||||
pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
|
||||
pdata->irq = irq_of_parse_and_map(of_node, 0);
|
||||
res = devm_request_irq(&op->dev, pdata->irq,
|
||||
mpc85xx_pci_isr,
|
||||
IRQF_SHARED,
|
||||
|
@ -386,8 +397,22 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
|
|||
devres_release_group(&op->dev, mpc85xx_pci_err_probe);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(mpc85xx_pci_err_probe);
|
||||
|
||||
static const struct platform_device_id mpc85xx_pci_err_match[] = {
|
||||
{
|
||||
.name = "mpc85xx-pci-edac"
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver mpc85xx_pci_err_driver = {
|
||||
.probe = mpc85xx_pci_err_probe,
|
||||
.id_table = mpc85xx_pci_err_match,
|
||||
.driver = {
|
||||
.name = "mpc85xx_pci_err",
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/**************************** L2 Err device ***************************/
|
||||
|
@ -1208,6 +1233,14 @@ static void __init mpc85xx_mc_clear_rfxe(void *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
static struct platform_driver * const drivers[] = {
|
||||
&mpc85xx_mc_err_driver,
|
||||
&mpc85xx_l2_err_driver,
|
||||
#ifdef CONFIG_PCI
|
||||
&mpc85xx_pci_err_driver,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init mpc85xx_mc_init(void)
|
||||
{
|
||||
int res = 0;
|
||||
|
@ -1226,13 +1259,9 @@ static int __init mpc85xx_mc_init(void)
|
|||
break;
|
||||
}
|
||||
|
||||
res = platform_driver_register(&mpc85xx_mc_err_driver);
|
||||
res = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
if (res)
|
||||
printk(KERN_WARNING EDAC_MOD_STR "MC fails to register\n");
|
||||
|
||||
res = platform_driver_register(&mpc85xx_l2_err_driver);
|
||||
if (res)
|
||||
printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
|
||||
printk(KERN_WARNING EDAC_MOD_STR "drivers fail to register\n");
|
||||
|
||||
#ifdef CONFIG_FSL_SOC_BOOKE
|
||||
pvr = mfspr(SPRN_PVR);
|
||||
|
@ -1270,8 +1299,7 @@ static void __exit mpc85xx_mc_exit(void)
|
|||
on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
|
||||
}
|
||||
#endif
|
||||
platform_driver_unregister(&mpc85xx_l2_err_driver);
|
||||
platform_driver_unregister(&mpc85xx_mc_err_driver);
|
||||
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
}
|
||||
|
||||
module_exit(mpc85xx_mc_exit);
|
||||
|
|
|
@ -847,6 +847,15 @@ static struct platform_driver mv64x60_mc_err_driver = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct platform_driver * const drivers[] = {
|
||||
&mv64x60_mc_err_driver,
|
||||
&mv64x60_cpu_err_driver,
|
||||
&mv64x60_sram_err_driver,
|
||||
#ifdef CONFIG_PCI
|
||||
&mv64x60_pci_err_driver,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init mv64x60_edac_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -863,39 +872,13 @@ static int __init mv64x60_edac_init(void)
|
|||
break;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&mv64x60_mc_err_driver);
|
||||
if (ret)
|
||||
printk(KERN_WARNING EDAC_MOD_STR "MC err failed to register\n");
|
||||
|
||||
ret = platform_driver_register(&mv64x60_cpu_err_driver);
|
||||
if (ret)
|
||||
printk(KERN_WARNING EDAC_MOD_STR
|
||||
"CPU err failed to register\n");
|
||||
|
||||
ret = platform_driver_register(&mv64x60_sram_err_driver);
|
||||
if (ret)
|
||||
printk(KERN_WARNING EDAC_MOD_STR
|
||||
"SRAM err failed to register\n");
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
ret = platform_driver_register(&mv64x60_pci_err_driver);
|
||||
if (ret)
|
||||
printk(KERN_WARNING EDAC_MOD_STR
|
||||
"PCI err failed to register\n");
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
}
|
||||
module_init(mv64x60_edac_init);
|
||||
|
||||
static void __exit mv64x60_edac_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
platform_driver_unregister(&mv64x60_pci_err_driver);
|
||||
#endif
|
||||
platform_driver_unregister(&mv64x60_sram_err_driver);
|
||||
platform_driver_unregister(&mv64x60_cpu_err_driver);
|
||||
platform_driver_unregister(&mv64x60_mc_err_driver);
|
||||
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
}
|
||||
module_exit(mv64x60_edac_exit);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,42 @@
|
|||
#include "edac_module.h"
|
||||
|
||||
static struct workqueue_struct *wq;
|
||||
|
||||
bool edac_queue_work(struct delayed_work *work, unsigned long delay)
|
||||
{
|
||||
return queue_delayed_work(wq, work, delay);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(edac_queue_work);
|
||||
|
||||
bool edac_mod_work(struct delayed_work *work, unsigned long delay)
|
||||
{
|
||||
return mod_delayed_work(wq, work, delay);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(edac_mod_work);
|
||||
|
||||
bool edac_stop_work(struct delayed_work *work)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
ret = cancel_delayed_work_sync(work);
|
||||
flush_workqueue(wq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(edac_stop_work);
|
||||
|
||||
int edac_workqueue_setup(void)
|
||||
{
|
||||
wq = create_singlethread_workqueue("edac-poller");
|
||||
if (!wq)
|
||||
return -ENODEV;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void edac_workqueue_teardown(void)
|
||||
{
|
||||
flush_workqueue(wq);
|
||||
destroy_workqueue(wq);
|
||||
wq = NULL;
|
||||
}
|
|
@ -28,12 +28,10 @@ struct device;
|
|||
extern int edac_op_state;
|
||||
extern int edac_err_assert;
|
||||
extern atomic_t edac_handlers;
|
||||
extern struct bus_type edac_subsys;
|
||||
|
||||
extern int edac_handler_set(void);
|
||||
extern void edac_atomic_assert_error(void);
|
||||
extern struct bus_type *edac_get_sysfs_subsys(void);
|
||||
extern void edac_put_sysfs_subsys(void);
|
||||
|
||||
enum {
|
||||
EDAC_REPORTING_ENABLED,
|
||||
|
@ -237,8 +235,10 @@ enum mem_type {
|
|||
#define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2)
|
||||
#define MEM_FLAG_RDDR2 BIT(MEM_RDDR2)
|
||||
#define MEM_FLAG_XDR BIT(MEM_XDR)
|
||||
#define MEM_FLAG_DDR3 BIT(MEM_DDR3)
|
||||
#define MEM_FLAG_RDDR3 BIT(MEM_RDDR3)
|
||||
#define MEM_FLAG_DDR3 BIT(MEM_DDR3)
|
||||
#define MEM_FLAG_RDDR3 BIT(MEM_RDDR3)
|
||||
#define MEM_FLAG_DDR4 BIT(MEM_DDR4)
|
||||
#define MEM_FLAG_RDDR4 BIT(MEM_RDDR4)
|
||||
|
||||
/**
|
||||
* enum edac-type - Error Detection and Correction capabilities and mode
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef FSL_EDAC_H
|
||||
#define FSL_EDAC_H
|
||||
|
||||
struct mpc85xx_edac_pci_plat_data {
|
||||
struct device_node *of_node;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue