/* the ktype for a pci instance */ staticstruct kobj_type ktype_pci_instance = {
.release = edac_pci_instance_release,
.sysfs_ops = &pci_instance_ops,
.default_groups = pci_instance_groups,
};
/* *edac_pci_create_instance_kobj * *constructoneEDACPCIinstance'skobjectforuse
*/ staticint edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
{ struct kobject *main_kobj; int err;
edac_dbg(0, "\n");
/* First bump the ref count on the top main kobj, which will *trackthenumberofPCIinstanceswehave,andthusnest *properlyonkeepingthemoduleloaded
*/
main_kobj = kobject_get(edac_pci_top_main_kobj); if (!main_kobj) {
err = -ENODEV; goto error_out;
}
/* And now register this new kobject under the main kobj */
err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance,
edac_pci_top_main_kobj, "pci%d", idx); if (err != 0) {
edac_dbg(2, "failed to register instance pci%d\n", idx);
kobject_put(edac_pci_top_main_kobj); goto error_out;
}
/* check and count if we have already created the main kobject */ if (atomic_inc_return(&edac_pci_sysfs_refcount) != 1) return0;
/* First time, so create the main kobject and its *controlsandattributes
*/
edac_subsys = edac_get_sysfs_subsys();
/* Bump the reference count on this module to ensure the *modulesisn'tunloadeduntilwedeconstructthetop *levelmainkobjforEDACPCI
*/ if (!try_module_get(THIS_MODULE)) {
edac_dbg(1, "try_module_get() failed\n"); goto decrement_count_fail;
}
edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); if (!edac_pci_top_main_kobj) {
edac_dbg(1, "Failed to allocate\n");
err = -ENOMEM; goto kzalloc_fail;
}
/* Instanstiate the pci object */
dev_root = bus_get_dev_root(edac_subsys); if (dev_root) {
err = kobject_init_and_add(edac_pci_top_main_kobj,
&ktype_edac_pci_main_kobj,
&dev_root->kobj, "pci");
put_device(dev_root);
} if (err) {
edac_dbg(1, "Failed to register '.../edac/pci'\n"); goto kobject_init_and_add_fail;
}
/* At this point, to 'release' the top level kobject *forEDACPCI,thenedac_pci_main_kobj_teardown() *mustbeused,forresourcestobecleanedupproperly
*/
kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD);
edac_dbg(1, "Registered '.../edac/pci' kobject\n");
/* Decrement the count and only if no more controller instances *areconnectedperformtheunregisterationofthetoplevel *mainkobj
*/ 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);
}
}
int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci)
{ int err; struct kobject *edac_kobj = &pci->kobj;
edac_dbg(0, "idx=%d\n", pci->pci_idx);
/* create the top main EDAC PCI kobject, IF needed */
err = edac_pci_main_kobj_setup(); if (err) return err;
/* Create this instance's kobject under the MAIN kobject */
err = edac_pci_create_instance_kobj(pci, pci->pci_idx); if (err) goto unregister_cleanup;
err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK); if (err) {
edac_dbg(0, "sysfs_create_link() returned err= %d\n", err); goto symlink_fail;
}
/* Remove the symlink */
sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK);
/* remove this PCI instance's sysfs entries */
edac_pci_unregister_sysfs_instance_kobj(pci);
/* Call the main unregister function, which will determine *ifthis'pci'isthelastinstance. *Ifitis,themainkobjectwillbeunregisteredasaresult
*/
edac_dbg(0, "calling edac_pci_main_kobj_teardown()\n");
edac_pci_main_kobj_teardown();
}
/************************ PCI error handling *************************/ 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 *pulledbuttheLinuxPCIlayerhasnotyetfinishedcleaningup. *Wedon'twanttoreportonsuchdevices
*/
if (status == 0xFFFF) {
u32 sanity;
pci_read_config_dword(dev, 0, &sanity);
if (sanity == 0xFFFFFFFF) return0;
}
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;
}
/* Clear any PCI parity errors logged by this device. */ staticvoid 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 & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE)
get_pci_parity_status(dev, 1);
}
/* check the status reg for errors on boards NOT marked as broken *ifbroken,wecannottrustanyofthestatusbits
*/ if (status && !dev->broken_parity_status) { if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) {
edac_printk(KERN_CRIT, EDAC_PCI, "Signaled System Error on %s\n",
pci_name(dev));
atomic_inc(&pci_nonparity_count);
}
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));
if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) { /* On bridges, need to examine secondary status register */
status = get_pci_parity_status(dev, 1);
/* check the secondary status reg for errors, *onNOTbrokenboards
*/ if (status && !dev->broken_parity_status) { if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) {
edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " "Signaled System Error on %s\n",
pci_name(dev));
atomic_inc(&pci_nonparity_count);
}
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);
}
}
}
}
/* reduce some complexity in definition of the iterator */ typedefvoid (*pci_parity_check_fn_t) (struct pci_dev *dev);
/* *edac_pci_do_parity_check * *performstheactualPCIparitycheckoperation
*/ void edac_pci_do_parity_check(void)
{ int before_count;
edac_dbg(3, "\n");
/* if policy has PCI check off, leave now */ if (!check_pci_errors) return;
before_count = atomic_read(&pci_parity_count);
/* scan all PCI devices looking for a Parity Error on devices and *bridges. *Theiteratorcallspci_get_device()whichmightsleep,thus *wecannotdisableinterruptsinthisscan.
*/
edac_pci_dev_parity_iterator(edac_pci_dev_parity_test);
/* Only if operator has selected panic on PCI Error */ if (edac_pci_get_panic_on_pe()) { /* If the count is different 'after' from 'before' */ if (before_count != atomic_read(&pci_parity_count))
panic("EDAC: PCI Parity Error");
}
}
/* *edac_pci_clear_parity_errors * *functiontoperformaniterationoverthePCIdevices *andclearntheircurrentstatus
*/ void edac_pci_clear_parity_errors(void)
{ /* Clear any PCI bus parity errors that devices initially have logged *intheirregisters.
*/
edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.