diff options
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r-- | drivers/edac/edac_mc.c | 538 |
1 files changed, 277 insertions, 261 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index ea06e3a4dc35..603de8b49f27 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
@@ -54,16 +54,17 @@ static int log_ce = 1; | |||
54 | static int panic_on_ue; | 54 | static int panic_on_ue; |
55 | static int poll_msec = 1000; | 55 | static int poll_msec = 1000; |
56 | 56 | ||
57 | static int check_pci_parity = 0; /* default YES check PCI parity */ | ||
58 | static int panic_on_pci_parity; /* default no panic on PCI Parity */ | ||
59 | static atomic_t pci_parity_count = ATOMIC_INIT(0); | ||
60 | |||
61 | /* lock to memory controller's control array */ | 57 | /* lock to memory controller's control array */ |
62 | static DECLARE_MUTEX(mem_ctls_mutex); | 58 | static DECLARE_MUTEX(mem_ctls_mutex); |
63 | static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); | 59 | static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); |
64 | 60 | ||
65 | static struct task_struct *edac_thread; | 61 | static struct task_struct *edac_thread; |
66 | 62 | ||
63 | #ifdef CONFIG_PCI | ||
64 | static int check_pci_parity = 0; /* default YES check PCI parity */ | ||
65 | static int panic_on_pci_parity; /* default no panic on PCI Parity */ | ||
66 | static atomic_t pci_parity_count = ATOMIC_INIT(0); | ||
67 | |||
67 | /* Structure of the whitelist and blacklist arrays */ | 68 | /* Structure of the whitelist and blacklist arrays */ |
68 | struct edac_pci_device_list { | 69 | struct edac_pci_device_list { |
69 | unsigned int vendor; /* Vendor ID */ | 70 | unsigned int vendor; /* Vendor ID */ |
@@ -80,6 +81,12 @@ static int pci_blacklist_count; | |||
80 | static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES]; | 81 | static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES]; |
81 | static int pci_whitelist_count ; | 82 | static int pci_whitelist_count ; |
82 | 83 | ||
84 | #ifndef DISABLE_EDAC_SYSFS | ||
85 | static struct kobject edac_pci_kobj; /* /sys/devices/system/edac/pci */ | ||
86 | static struct completion edac_pci_kobj_complete; | ||
87 | #endif /* DISABLE_EDAC_SYSFS */ | ||
88 | #endif /* CONFIG_PCI */ | ||
89 | |||
83 | /* START sysfs data and methods */ | 90 | /* START sysfs data and methods */ |
84 | 91 | ||
85 | #ifndef DISABLE_EDAC_SYSFS | 92 | #ifndef DISABLE_EDAC_SYSFS |
@@ -127,18 +134,15 @@ static struct sysdev_class edac_class = { | |||
127 | set_kset_name("edac"), | 134 | set_kset_name("edac"), |
128 | }; | 135 | }; |
129 | 136 | ||
130 | /* sysfs objects: | 137 | /* sysfs object: |
131 | * /sys/devices/system/edac/mc | 138 | * /sys/devices/system/edac/mc |
132 | * /sys/devices/system/edac/pci | ||
133 | */ | 139 | */ |
134 | static struct kobject edac_memctrl_kobj; | 140 | static struct kobject edac_memctrl_kobj; |
135 | static struct kobject edac_pci_kobj; | ||
136 | 141 | ||
137 | /* We use these to wait for the reference counts on edac_memctrl_kobj and | 142 | /* We use these to wait for the reference counts on edac_memctrl_kobj and |
138 | * edac_pci_kobj to reach 0. | 143 | * edac_pci_kobj to reach 0. |
139 | */ | 144 | */ |
140 | static struct completion edac_memctrl_kobj_complete; | 145 | static struct completion edac_memctrl_kobj_complete; |
141 | static struct completion edac_pci_kobj_complete; | ||
142 | 146 | ||
143 | /* | 147 | /* |
144 | * /sys/devices/system/edac/mc; | 148 | * /sys/devices/system/edac/mc; |
@@ -324,6 +328,8 @@ static void edac_sysfs_memctrl_teardown(void) | |||
324 | #endif /* DISABLE_EDAC_SYSFS */ | 328 | #endif /* DISABLE_EDAC_SYSFS */ |
325 | } | 329 | } |
326 | 330 | ||
331 | #ifdef CONFIG_PCI | ||
332 | |||
327 | #ifndef DISABLE_EDAC_SYSFS | 333 | #ifndef DISABLE_EDAC_SYSFS |
328 | 334 | ||
329 | /* | 335 | /* |
@@ -624,6 +630,252 @@ static void edac_sysfs_pci_teardown(void) | |||
624 | #endif | 630 | #endif |
625 | } | 631 | } |
626 | 632 | ||
633 | |||
634 | static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) | ||
635 | { | ||
636 | int where; | ||
637 | u16 status; | ||
638 | |||
639 | where = secondary ? PCI_SEC_STATUS : PCI_STATUS; | ||
640 | pci_read_config_word(dev, where, &status); | ||
641 | |||
642 | /* If we get back 0xFFFF then we must suspect that the card has been | ||
643 | * pulled but the Linux PCI layer has not yet finished cleaning up. | ||
644 | * We don't want to report on such devices | ||
645 | */ | ||
646 | |||
647 | if (status == 0xFFFF) { | ||
648 | u32 sanity; | ||
649 | |||
650 | pci_read_config_dword(dev, 0, &sanity); | ||
651 | |||
652 | if (sanity == 0xFFFFFFFF) | ||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR | | ||
657 | PCI_STATUS_PARITY; | ||
658 | |||
659 | if (status) | ||
660 | /* reset only the bits we are interested in */ | ||
661 | pci_write_config_word(dev, where, status); | ||
662 | |||
663 | return status; | ||
664 | } | ||
665 | |||
666 | typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev); | ||
667 | |||
668 | /* Clear any PCI parity errors logged by this device. */ | ||
669 | static void edac_pci_dev_parity_clear(struct pci_dev *dev) | ||
670 | { | ||
671 | u8 header_type; | ||
672 | |||
673 | get_pci_parity_status(dev, 0); | ||
674 | |||
675 | /* read the device TYPE, looking for bridges */ | ||
676 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
677 | |||
678 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) | ||
679 | get_pci_parity_status(dev, 1); | ||
680 | } | ||
681 | |||
682 | /* | ||
683 | * PCI Parity polling | ||
684 | * | ||
685 | */ | ||
686 | static void edac_pci_dev_parity_test(struct pci_dev *dev) | ||
687 | { | ||
688 | u16 status; | ||
689 | u8 header_type; | ||
690 | |||
691 | /* read the STATUS register on this device | ||
692 | */ | ||
693 | status = get_pci_parity_status(dev, 0); | ||
694 | |||
695 | debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id ); | ||
696 | |||
697 | /* check the status reg for errors */ | ||
698 | if (status) { | ||
699 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) | ||
700 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
701 | "Signaled System Error on %s\n", | ||
702 | pci_name(dev)); | ||
703 | |||
704 | if (status & (PCI_STATUS_PARITY)) { | ||
705 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
706 | "Master Data Parity Error on %s\n", | ||
707 | pci_name(dev)); | ||
708 | |||
709 | atomic_inc(&pci_parity_count); | ||
710 | } | ||
711 | |||
712 | if (status & (PCI_STATUS_DETECTED_PARITY)) { | ||
713 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
714 | "Detected Parity Error on %s\n", | ||
715 | pci_name(dev)); | ||
716 | |||
717 | atomic_inc(&pci_parity_count); | ||
718 | } | ||
719 | } | ||
720 | |||
721 | /* read the device TYPE, looking for bridges */ | ||
722 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
723 | |||
724 | debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id ); | ||
725 | |||
726 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | ||
727 | /* On bridges, need to examine secondary status register */ | ||
728 | status = get_pci_parity_status(dev, 1); | ||
729 | |||
730 | debugf2("PCI SEC_STATUS= 0x%04x %s\n", | ||
731 | status, dev->dev.bus_id ); | ||
732 | |||
733 | /* check the secondary status reg for errors */ | ||
734 | if (status) { | ||
735 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) | ||
736 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
737 | "Signaled System Error on %s\n", | ||
738 | pci_name(dev)); | ||
739 | |||
740 | if (status & (PCI_STATUS_PARITY)) { | ||
741 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
742 | "Master Data Parity Error on " | ||
743 | "%s\n", pci_name(dev)); | ||
744 | |||
745 | atomic_inc(&pci_parity_count); | ||
746 | } | ||
747 | |||
748 | if (status & (PCI_STATUS_DETECTED_PARITY)) { | ||
749 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
750 | "Detected Parity Error on %s\n", | ||
751 | pci_name(dev)); | ||
752 | |||
753 | atomic_inc(&pci_parity_count); | ||
754 | } | ||
755 | } | ||
756 | } | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * check_dev_on_list: Scan for a PCI device on a white/black list | ||
761 | * @list: an EDAC &edac_pci_device_list white/black list pointer | ||
762 | * @free_index: index of next free entry on the list | ||
763 | * @pci_dev: PCI Device pointer | ||
764 | * | ||
765 | * see if list contains the device. | ||
766 | * | ||
767 | * Returns: 0 not found | ||
768 | * 1 found on list | ||
769 | */ | ||
770 | static int check_dev_on_list(struct edac_pci_device_list *list, | ||
771 | int free_index, struct pci_dev *dev) | ||
772 | { | ||
773 | int i; | ||
774 | int rc = 0; /* Assume not found */ | ||
775 | unsigned short vendor=dev->vendor; | ||
776 | unsigned short device=dev->device; | ||
777 | |||
778 | /* Scan the list, looking for a vendor/device match */ | ||
779 | for (i = 0; i < free_index; i++, list++ ) { | ||
780 | if ((list->vendor == vendor ) && (list->device == device )) { | ||
781 | rc = 1; | ||
782 | break; | ||
783 | } | ||
784 | } | ||
785 | |||
786 | return rc; | ||
787 | } | ||
788 | |||
789 | /* | ||
790 | * pci_dev parity list iterator | ||
791 | * Scan the PCI device list for one iteration, looking for SERRORs | ||
792 | * Master Parity ERRORS or Parity ERRORs on primary or secondary devices | ||
793 | */ | ||
794 | static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) | ||
795 | { | ||
796 | struct pci_dev *dev = NULL; | ||
797 | |||
798 | /* request for kernel access to the next PCI device, if any, | ||
799 | * and while we are looking at it have its reference count | ||
800 | * bumped until we are done with it | ||
801 | */ | ||
802 | while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
803 | /* if whitelist exists then it has priority, so only scan | ||
804 | * those devices on the whitelist | ||
805 | */ | ||
806 | if (pci_whitelist_count > 0 ) { | ||
807 | if (check_dev_on_list(pci_whitelist, | ||
808 | pci_whitelist_count, dev)) | ||
809 | fn(dev); | ||
810 | } else { | ||
811 | /* | ||
812 | * if no whitelist, then check if this devices is | ||
813 | * blacklisted | ||
814 | */ | ||
815 | if (!check_dev_on_list(pci_blacklist, | ||
816 | pci_blacklist_count, dev)) | ||
817 | fn(dev); | ||
818 | } | ||
819 | } | ||
820 | } | ||
821 | |||
822 | static void do_pci_parity_check(void) | ||
823 | { | ||
824 | unsigned long flags; | ||
825 | int before_count; | ||
826 | |||
827 | debugf3("%s()\n", __func__); | ||
828 | |||
829 | if (!check_pci_parity) | ||
830 | return; | ||
831 | |||
832 | before_count = atomic_read(&pci_parity_count); | ||
833 | |||
834 | /* scan all PCI devices looking for a Parity Error on devices and | ||
835 | * bridges | ||
836 | */ | ||
837 | local_irq_save(flags); | ||
838 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_test); | ||
839 | local_irq_restore(flags); | ||
840 | |||
841 | /* Only if operator has selected panic on PCI Error */ | ||
842 | if (panic_on_pci_parity) { | ||
843 | /* If the count is different 'after' from 'before' */ | ||
844 | if (before_count != atomic_read(&pci_parity_count)) | ||
845 | panic("EDAC: PCI Parity Error"); | ||
846 | } | ||
847 | } | ||
848 | |||
849 | static inline void clear_pci_parity_errors(void) | ||
850 | { | ||
851 | /* Clear any PCI bus parity errors that devices initially have logged | ||
852 | * in their registers. | ||
853 | */ | ||
854 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); | ||
855 | } | ||
856 | |||
857 | #else /* CONFIG_PCI */ | ||
858 | |||
859 | static inline void do_pci_parity_check(void) | ||
860 | { | ||
861 | /* no-op */ | ||
862 | } | ||
863 | |||
864 | static inline void clear_pci_parity_errors(void) | ||
865 | { | ||
866 | /* no-op */ | ||
867 | } | ||
868 | |||
869 | static void edac_sysfs_pci_teardown(void) | ||
870 | { | ||
871 | } | ||
872 | |||
873 | static int edac_sysfs_pci_setup(void) | ||
874 | { | ||
875 | return 0; | ||
876 | } | ||
877 | #endif /* CONFIG_PCI */ | ||
878 | |||
627 | #ifndef DISABLE_EDAC_SYSFS | 879 | #ifndef DISABLE_EDAC_SYSFS |
628 | 880 | ||
629 | /* EDAC sysfs CSROW data structures and methods */ | 881 | /* EDAC sysfs CSROW data structures and methods */ |
@@ -1132,7 +1384,7 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) | |||
1132 | return err; | 1384 | return err; |
1133 | 1385 | ||
1134 | /* create a symlink for the device */ | 1386 | /* create a symlink for the device */ |
1135 | err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj, | 1387 | err = sysfs_create_link(edac_mci_kobj, &mci->dev->kobj, |
1136 | EDAC_DEVICE_SYMLINK); | 1388 | EDAC_DEVICE_SYMLINK); |
1137 | 1389 | ||
1138 | if (err) | 1390 | if (err) |
@@ -1238,7 +1490,7 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci) | |||
1238 | debugf4("\tmci->edac_check = %p\n", mci->edac_check); | 1490 | debugf4("\tmci->edac_check = %p\n", mci->edac_check); |
1239 | debugf3("\tmci->nr_csrows = %d, csrows = %p\n", | 1491 | debugf3("\tmci->nr_csrows = %d, csrows = %p\n", |
1240 | mci->nr_csrows, mci->csrows); | 1492 | mci->nr_csrows, mci->csrows); |
1241 | debugf3("\tpdev = %p\n", mci->pdev); | 1493 | debugf3("\tdev = %p\n", mci->dev); |
1242 | debugf3("\tmod_name:ctl_name = %s:%s\n", | 1494 | debugf3("\tmod_name:ctl_name = %s:%s\n", |
1243 | mci->mod_name, mci->ctl_name); | 1495 | mci->mod_name, mci->ctl_name); |
1244 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); | 1496 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); |
@@ -1363,7 +1615,7 @@ void edac_mc_free(struct mem_ctl_info *mci) | |||
1363 | } | 1615 | } |
1364 | EXPORT_SYMBOL_GPL(edac_mc_free); | 1616 | EXPORT_SYMBOL_GPL(edac_mc_free); |
1365 | 1617 | ||
1366 | static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev) | 1618 | static struct mem_ctl_info *find_mci_by_dev(struct device *dev) |
1367 | { | 1619 | { |
1368 | struct mem_ctl_info *mci; | 1620 | struct mem_ctl_info *mci; |
1369 | struct list_head *item; | 1621 | struct list_head *item; |
@@ -1373,7 +1625,7 @@ static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev) | |||
1373 | list_for_each(item, &mc_devices) { | 1625 | list_for_each(item, &mc_devices) { |
1374 | mci = list_entry(item, struct mem_ctl_info, link); | 1626 | mci = list_entry(item, struct mem_ctl_info, link); |
1375 | 1627 | ||
1376 | if (mci->pdev == pdev) | 1628 | if (mci->dev == dev) |
1377 | return mci; | 1629 | return mci; |
1378 | } | 1630 | } |
1379 | 1631 | ||
@@ -1390,12 +1642,12 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci) | |||
1390 | mci->mc_idx = 0; | 1642 | mci->mc_idx = 0; |
1391 | insert_before = &mc_devices; | 1643 | insert_before = &mc_devices; |
1392 | } else { | 1644 | } else { |
1393 | if (find_mci_by_pdev(mci->pdev)) { | 1645 | if (find_mci_by_dev(mci->dev)) { |
1394 | edac_printk(KERN_WARNING, EDAC_MC, | 1646 | edac_printk(KERN_WARNING, EDAC_MC, |
1395 | "%s (%s) %s %s already assigned %d\n", | 1647 | "%s (%s) %s %s already assigned %d\n", |
1396 | mci->pdev->dev.bus_id, | 1648 | mci->dev->bus_id, dev_name(mci->dev), |
1397 | pci_name(mci->pdev), mci->mod_name, | 1649 | mci->mod_name, mci->ctl_name, |
1398 | mci->ctl_name, mci->mc_idx); | 1650 | mci->mc_idx); |
1399 | return 1; | 1651 | return 1; |
1400 | } | 1652 | } |
1401 | 1653 | ||
@@ -1486,8 +1738,8 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) | |||
1486 | } | 1738 | } |
1487 | 1739 | ||
1488 | /* Report action taken */ | 1740 | /* Report action taken */ |
1489 | edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: PCI %s\n", | 1741 | edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n", |
1490 | mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); | 1742 | mci->mod_name, mci->ctl_name, dev_name(mci->dev)); |
1491 | 1743 | ||
1492 | up(&mem_ctls_mutex); | 1744 | up(&mem_ctls_mutex); |
1493 | return 0; | 1745 | return 0; |
@@ -1504,18 +1756,18 @@ EXPORT_SYMBOL_GPL(edac_mc_add_mc); | |||
1504 | /** | 1756 | /** |
1505 | * edac_mc_del_mc: Remove sysfs entries for specified mci structure and | 1757 | * edac_mc_del_mc: Remove sysfs entries for specified mci structure and |
1506 | * remove mci structure from global list | 1758 | * remove mci structure from global list |
1507 | * @pdev: Pointer to 'struct pci_dev' representing mci structure to remove. | 1759 | * @pdev: Pointer to 'struct device' representing mci structure to remove. |
1508 | * | 1760 | * |
1509 | * Return pointer to removed mci structure, or NULL if device not found. | 1761 | * Return pointer to removed mci structure, or NULL if device not found. |
1510 | */ | 1762 | */ |
1511 | struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev) | 1763 | struct mem_ctl_info * edac_mc_del_mc(struct device *dev) |
1512 | { | 1764 | { |
1513 | struct mem_ctl_info *mci; | 1765 | struct mem_ctl_info *mci; |
1514 | 1766 | ||
1515 | debugf0("MC: %s()\n", __func__); | 1767 | debugf0("MC: %s()\n", __func__); |
1516 | down(&mem_ctls_mutex); | 1768 | down(&mem_ctls_mutex); |
1517 | 1769 | ||
1518 | if ((mci = find_mci_by_pdev(pdev)) == NULL) { | 1770 | if ((mci = find_mci_by_dev(dev)) == NULL) { |
1519 | up(&mem_ctls_mutex); | 1771 | up(&mem_ctls_mutex); |
1520 | return NULL; | 1772 | return NULL; |
1521 | } | 1773 | } |
@@ -1524,8 +1776,8 @@ struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev) | |||
1524 | del_mc_from_global_list(mci); | 1776 | del_mc_from_global_list(mci); |
1525 | up(&mem_ctls_mutex); | 1777 | up(&mem_ctls_mutex); |
1526 | edac_printk(KERN_INFO, EDAC_MC, | 1778 | edac_printk(KERN_INFO, EDAC_MC, |
1527 | "Removed device %d for %s %s: PCI %s\n", mci->mc_idx, | 1779 | "Removed device %d for %s %s: DEV %s\n", mci->mc_idx, |
1528 | mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); | 1780 | mci->mod_name, mci->ctl_name, dev_name(mci->dev)); |
1529 | return mci; | 1781 | return mci; |
1530 | } | 1782 | } |
1531 | EXPORT_SYMBOL_GPL(edac_mc_del_mc); | 1783 | 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) | |||
1739 | } | 1991 | } |
1740 | EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); | 1992 | EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); |
1741 | 1993 | ||
1742 | #ifdef CONFIG_PCI | ||
1743 | |||
1744 | static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) | ||
1745 | { | ||
1746 | int where; | ||
1747 | u16 status; | ||
1748 | |||
1749 | where = secondary ? PCI_SEC_STATUS : PCI_STATUS; | ||
1750 | pci_read_config_word(dev, where, &status); | ||
1751 | |||
1752 | /* If we get back 0xFFFF then we must suspect that the card has been | ||
1753 | * pulled but the Linux PCI layer has not yet finished cleaning up. | ||
1754 | * We don't want to report on such devices | ||
1755 | */ | ||
1756 | |||
1757 | if (status == 0xFFFF) { | ||
1758 | u32 sanity; | ||
1759 | |||
1760 | pci_read_config_dword(dev, 0, &sanity); | ||
1761 | |||
1762 | if (sanity == 0xFFFFFFFF) | ||
1763 | return 0; | ||
1764 | } | ||
1765 | |||
1766 | status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR | | ||
1767 | PCI_STATUS_PARITY; | ||
1768 | |||
1769 | if (status) | ||
1770 | /* reset only the bits we are interested in */ | ||
1771 | pci_write_config_word(dev, where, status); | ||
1772 | |||
1773 | return status; | ||
1774 | } | ||
1775 | |||
1776 | typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev); | ||
1777 | |||
1778 | /* Clear any PCI parity errors logged by this device. */ | ||
1779 | static void edac_pci_dev_parity_clear(struct pci_dev *dev) | ||
1780 | { | ||
1781 | u8 header_type; | ||
1782 | |||
1783 | get_pci_parity_status(dev, 0); | ||
1784 | |||
1785 | /* read the device TYPE, looking for bridges */ | ||
1786 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
1787 | |||
1788 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) | ||
1789 | get_pci_parity_status(dev, 1); | ||
1790 | } | ||
1791 | |||
1792 | /* | ||
1793 | * PCI Parity polling | ||
1794 | * | ||
1795 | */ | ||
1796 | static void edac_pci_dev_parity_test(struct pci_dev *dev) | ||
1797 | { | ||
1798 | u16 status; | ||
1799 | u8 header_type; | ||
1800 | |||
1801 | /* read the STATUS register on this device | ||
1802 | */ | ||
1803 | status = get_pci_parity_status(dev, 0); | ||
1804 | |||
1805 | debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id ); | ||
1806 | |||
1807 | /* check the status reg for errors */ | ||
1808 | if (status) { | ||
1809 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) | ||
1810 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
1811 | "Signaled System Error on %s\n", | ||
1812 | pci_name(dev)); | ||
1813 | |||
1814 | if (status & (PCI_STATUS_PARITY)) { | ||
1815 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
1816 | "Master Data Parity Error on %s\n", | ||
1817 | pci_name(dev)); | ||
1818 | |||
1819 | atomic_inc(&pci_parity_count); | ||
1820 | } | ||
1821 | |||
1822 | if (status & (PCI_STATUS_DETECTED_PARITY)) { | ||
1823 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
1824 | "Detected Parity Error on %s\n", | ||
1825 | pci_name(dev)); | ||
1826 | |||
1827 | atomic_inc(&pci_parity_count); | ||
1828 | } | ||
1829 | } | ||
1830 | |||
1831 | /* read the device TYPE, looking for bridges */ | ||
1832 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
1833 | |||
1834 | debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id ); | ||
1835 | |||
1836 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | ||
1837 | /* On bridges, need to examine secondary status register */ | ||
1838 | status = get_pci_parity_status(dev, 1); | ||
1839 | |||
1840 | debugf2("PCI SEC_STATUS= 0x%04x %s\n", | ||
1841 | status, dev->dev.bus_id ); | ||
1842 | |||
1843 | /* check the secondary status reg for errors */ | ||
1844 | if (status) { | ||
1845 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) | ||
1846 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
1847 | "Signaled System Error on %s\n", | ||
1848 | pci_name(dev)); | ||
1849 | |||
1850 | if (status & (PCI_STATUS_PARITY)) { | ||
1851 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
1852 | "Master Data Parity Error on " | ||
1853 | "%s\n", pci_name(dev)); | ||
1854 | |||
1855 | atomic_inc(&pci_parity_count); | ||
1856 | } | ||
1857 | |||
1858 | if (status & (PCI_STATUS_DETECTED_PARITY)) { | ||
1859 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
1860 | "Detected Parity Error on %s\n", | ||
1861 | pci_name(dev)); | ||
1862 | |||
1863 | atomic_inc(&pci_parity_count); | ||
1864 | } | ||
1865 | } | ||
1866 | } | ||
1867 | } | ||
1868 | |||
1869 | /* | ||
1870 | * check_dev_on_list: Scan for a PCI device on a white/black list | ||
1871 | * @list: an EDAC &edac_pci_device_list white/black list pointer | ||
1872 | * @free_index: index of next free entry on the list | ||
1873 | * @pci_dev: PCI Device pointer | ||
1874 | * | ||
1875 | * see if list contains the device. | ||
1876 | * | ||
1877 | * Returns: 0 not found | ||
1878 | * 1 found on list | ||
1879 | */ | ||
1880 | static int check_dev_on_list(struct edac_pci_device_list *list, | ||
1881 | int free_index, struct pci_dev *dev) | ||
1882 | { | ||
1883 | int i; | ||
1884 | int rc = 0; /* Assume not found */ | ||
1885 | unsigned short vendor=dev->vendor; | ||
1886 | unsigned short device=dev->device; | ||
1887 | |||
1888 | /* Scan the list, looking for a vendor/device match */ | ||
1889 | for (i = 0; i < free_index; i++, list++ ) { | ||
1890 | if ((list->vendor == vendor ) && (list->device == device )) { | ||
1891 | rc = 1; | ||
1892 | break; | ||
1893 | } | ||
1894 | } | ||
1895 | |||
1896 | return rc; | ||
1897 | } | ||
1898 | |||
1899 | /* | ||
1900 | * pci_dev parity list iterator | ||
1901 | * Scan the PCI device list for one iteration, looking for SERRORs | ||
1902 | * Master Parity ERRORS or Parity ERRORs on primary or secondary devices | ||
1903 | */ | ||
1904 | static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) | ||
1905 | { | ||
1906 | struct pci_dev *dev = NULL; | ||
1907 | |||
1908 | /* request for kernel access to the next PCI device, if any, | ||
1909 | * and while we are looking at it have its reference count | ||
1910 | * bumped until we are done with it | ||
1911 | */ | ||
1912 | while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
1913 | /* if whitelist exists then it has priority, so only scan | ||
1914 | * those devices on the whitelist | ||
1915 | */ | ||
1916 | if (pci_whitelist_count > 0 ) { | ||
1917 | if (check_dev_on_list(pci_whitelist, | ||
1918 | pci_whitelist_count, dev)) | ||
1919 | fn(dev); | ||
1920 | } else { | ||
1921 | /* | ||
1922 | * if no whitelist, then check if this devices is | ||
1923 | * blacklisted | ||
1924 | */ | ||
1925 | if (!check_dev_on_list(pci_blacklist, | ||
1926 | pci_blacklist_count, dev)) | ||
1927 | fn(dev); | ||
1928 | } | ||
1929 | } | ||
1930 | } | ||
1931 | |||
1932 | static void do_pci_parity_check(void) | ||
1933 | { | ||
1934 | unsigned long flags; | ||
1935 | int before_count; | ||
1936 | |||
1937 | debugf3("%s()\n", __func__); | ||
1938 | |||
1939 | if (!check_pci_parity) | ||
1940 | return; | ||
1941 | |||
1942 | before_count = atomic_read(&pci_parity_count); | ||
1943 | |||
1944 | /* scan all PCI devices looking for a Parity Error on devices and | ||
1945 | * bridges | ||
1946 | */ | ||
1947 | local_irq_save(flags); | ||
1948 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_test); | ||
1949 | local_irq_restore(flags); | ||
1950 | |||
1951 | /* Only if operator has selected panic on PCI Error */ | ||
1952 | if (panic_on_pci_parity) { | ||
1953 | /* If the count is different 'after' from 'before' */ | ||
1954 | if (before_count != atomic_read(&pci_parity_count)) | ||
1955 | panic("EDAC: PCI Parity Error"); | ||
1956 | } | ||
1957 | } | ||
1958 | |||
1959 | static inline void clear_pci_parity_errors(void) | ||
1960 | { | ||
1961 | /* Clear any PCI bus parity errors that devices initially have logged | ||
1962 | * in their registers. | ||
1963 | */ | ||
1964 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); | ||
1965 | } | ||
1966 | |||
1967 | #else /* CONFIG_PCI */ | ||
1968 | |||
1969 | static inline void do_pci_parity_check(void) | ||
1970 | { | ||
1971 | /* no-op */ | ||
1972 | } | ||
1973 | |||
1974 | static inline void clear_pci_parity_errors(void) | ||
1975 | { | ||
1976 | /* no-op */ | ||
1977 | } | ||
1978 | |||
1979 | #endif /* CONFIG_PCI */ | ||
1980 | 1994 | ||
1981 | /* | 1995 | /* |
1982 | * Iterate over all MC instances and check for ECC, et al, errors | 1996 | * Iterate over all MC instances and check for ECC, et al, errors |
@@ -2096,10 +2110,12 @@ MODULE_DESCRIPTION("Core library routines for MC reporting"); | |||
2096 | 2110 | ||
2097 | module_param(panic_on_ue, int, 0644); | 2111 | module_param(panic_on_ue, int, 0644); |
2098 | MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on"); | 2112 | MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on"); |
2113 | #ifdef CONFIG_PCI | ||
2099 | module_param(check_pci_parity, int, 0644); | 2114 | module_param(check_pci_parity, int, 0644); |
2100 | MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on"); | 2115 | MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on"); |
2101 | module_param(panic_on_pci_parity, int, 0644); | 2116 | module_param(panic_on_pci_parity, int, 0644); |
2102 | MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on"); | 2117 | MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on"); |
2118 | #endif | ||
2103 | module_param(log_ue, int, 0644); | 2119 | module_param(log_ue, int, 0644); |
2104 | MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on"); | 2120 | MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on"); |
2105 | module_param(log_ce, int, 0644); | 2121 | module_param(log_ce, int, 0644); |