1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/delay.h>
25#include <linux/sched.h>
26#include <linux/init.h>
27#include <linux/list.h>
28#include <linux/pci.h>
29#include <linux/proc_fs.h>
30#include <linux/rbtree.h>
31#include <linux/seq_file.h>
32#include <linux/spinlock.h>
33#include <linux/export.h>
34#include <linux/of.h>
35
36#include <linux/atomic.h>
37#include <asm/eeh.h>
38#include <asm/eeh_event.h>
39#include <asm/io.h>
40#include <asm/machdep.h>
41#include <asm/ppc-pci.h>
42#include <asm/rtas.h>
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84#define EEH_MAX_FAILS 2100000
85
86
87#define PCI_BUS_RESET_WAIT_MSEC (60*1000)
88
89
90struct eeh_ops *eeh_ops = NULL;
91
92int eeh_subsystem_enabled;
93EXPORT_SYMBOL(eeh_subsystem_enabled);
94
95
96
97
98
99
100
101
102
103
104int eeh_probe_mode;
105
106
107DEFINE_RAW_SPINLOCK(confirm_error_lock);
108
109
110
111
112
113#define EEH_PCI_REGS_LOG_LEN 4096
114static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN];
115
116
117
118
119
120
121struct eeh_stats {
122 u64 no_device;
123 u64 no_dn;
124 u64 no_cfg_addr;
125 u64 ignored_check;
126 u64 total_mmio_ffs;
127 u64 false_positives;
128 u64 slot_resets;
129};
130
131static struct eeh_stats eeh_stats;
132
133#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
134
135
136
137
138
139
140
141
142
143
144static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
145{
146 struct device_node *dn = eeh_dev_to_of_node(edev);
147 struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
148 u32 cfg;
149 int cap, i;
150 int n = 0;
151
152 n += scnprintf(buf+n, len-n, "%s\n", dn->full_name);
153 printk(KERN_WARNING "EEH: of node=%s\n", dn->full_name);
154
155 eeh_ops->read_config(dn, PCI_VENDOR_ID, 4, &cfg);
156 n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg);
157 printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg);
158
159 eeh_ops->read_config(dn, PCI_COMMAND, 4, &cfg);
160 n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
161 printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg);
162
163 if (!dev) {
164 printk(KERN_WARNING "EEH: no PCI device for this of node\n");
165 return n;
166 }
167
168
169 if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
170 eeh_ops->read_config(dn, PCI_SEC_STATUS, 2, &cfg);
171 n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg);
172 printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg);
173
174 eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &cfg);
175 n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg);
176 printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg);
177 }
178
179
180 cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
181 if (cap) {
182 eeh_ops->read_config(dn, cap, 4, &cfg);
183 n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);
184 printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg);
185
186 eeh_ops->read_config(dn, cap+4, 4, &cfg);
187 n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg);
188 printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg);
189 }
190
191
192 cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
193 if (cap) {
194 n += scnprintf(buf+n, len-n, "pci-e cap10:\n");
195 printk(KERN_WARNING
196 "EEH: PCI-E capabilities and status follow:\n");
197
198 for (i=0; i<=8; i++) {
199 eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
200 n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
201 printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg);
202 }
203
204 cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
205 if (cap) {
206 n += scnprintf(buf+n, len-n, "pci-e AER:\n");
207 printk(KERN_WARNING
208 "EEH: PCI-E AER capability register set follows:\n");
209
210 for (i=0; i<14; i++) {
211 eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
212 n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
213 printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg);
214 }
215 }
216 }
217
218 return n;
219}
220
221
222
223
224
225
226
227
228
229
230
231void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
232{
233 size_t loglen = 0;
234 struct eeh_dev *edev, *tmp;
235 bool valid_cfg_log = true;
236
237
238
239
240
241
242
243 if (eeh_probe_mode_dev() &&
244 (pe->type & EEH_PE_PHB) &&
245 (pe->state & (EEH_PE_ISOLATED | EEH_PE_PHB_DEAD)))
246 valid_cfg_log = false;
247
248 if (valid_cfg_log) {
249 eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
250 eeh_ops->configure_bridge(pe);
251 eeh_pe_restore_bars(pe);
252
253 pci_regs_buf[0] = 0;
254 eeh_pe_for_each_dev(pe, edev, tmp) {
255 loglen += eeh_gather_pci_data(edev, pci_regs_buf + loglen,
256 EEH_PCI_REGS_LOG_LEN - loglen);
257 }
258 }
259
260 eeh_ops->get_log(pe, severity, pci_regs_buf, loglen);
261}
262
263
264
265
266
267
268
269
270static inline unsigned long eeh_token_to_phys(unsigned long token)
271{
272 pte_t *ptep;
273 unsigned long pa;
274 int hugepage_shift;
275
276
277
278
279 ptep = find_linux_pte_or_hugepte(init_mm.pgd, token, &hugepage_shift);
280 if (!ptep)
281 return token;
282 WARN_ON(hugepage_shift);
283 pa = pte_pfn(*ptep) << PAGE_SHIFT;
284
285 return pa | (token & (PAGE_SIZE-1));
286}
287
288
289
290
291
292
293static int eeh_phb_check_failure(struct eeh_pe *pe)
294{
295 struct eeh_pe *phb_pe;
296 unsigned long flags;
297 int ret;
298
299 if (!eeh_probe_mode_dev())
300 return -EPERM;
301
302
303 phb_pe = eeh_phb_pe_get(pe->phb);
304 if (!phb_pe) {
305 pr_warning("%s Can't find PE for PHB#%d\n",
306 __func__, pe->phb->global_number);
307 return -EEXIST;
308 }
309
310
311 eeh_serialize_lock(&flags);
312 if (phb_pe->state & (EEH_PE_ISOLATED | EEH_PE_PHB_DEAD)) {
313 ret = 0;
314 goto out;
315 }
316
317
318 ret = eeh_ops->get_state(phb_pe, NULL);
319 if ((ret < 0) ||
320 (ret == EEH_STATE_NOT_SUPPORT) ||
321 (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) ==
322 (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) {
323 ret = 0;
324 goto out;
325 }
326
327
328 eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED);
329 eeh_serialize_unlock(flags);
330 eeh_send_failure_event(phb_pe);
331
332 pr_err("EEH: PHB#%x failure detected\n",
333 phb_pe->phb->global_number);
334 dump_stack();
335
336 return 1;
337out:
338 eeh_serialize_unlock(flags);
339 return ret;
340}
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356int eeh_dev_check_failure(struct eeh_dev *edev)
357{
358 int ret;
359 unsigned long flags;
360 struct device_node *dn;
361 struct pci_dev *dev;
362 struct eeh_pe *pe;
363 int rc = 0;
364 const char *location;
365
366 eeh_stats.total_mmio_ffs++;
367
368 if (!eeh_subsystem_enabled)
369 return 0;
370
371 if (!edev) {
372 eeh_stats.no_dn++;
373 return 0;
374 }
375 dn = eeh_dev_to_of_node(edev);
376 dev = eeh_dev_to_pci_dev(edev);
377 pe = edev->pe;
378
379
380 if (!pe) {
381 eeh_stats.ignored_check++;
382 pr_debug("EEH: Ignored check for %s %s\n",
383 eeh_pci_name(dev), dn->full_name);
384 return 0;
385 }
386
387 if (!pe->addr && !pe->config_addr) {
388 eeh_stats.no_cfg_addr++;
389 return 0;
390 }
391
392
393
394
395
396 ret = eeh_phb_check_failure(pe);
397 if (ret > 0)
398 return ret;
399
400
401
402
403
404
405
406 eeh_serialize_lock(&flags);
407 rc = 1;
408 if (pe->state & EEH_PE_ISOLATED) {
409 pe->check_count++;
410 if (pe->check_count % EEH_MAX_FAILS == 0) {
411 location = of_get_property(dn, "ibm,loc-code", NULL);
412 printk(KERN_ERR "EEH: %d reads ignored for recovering device at "
413 "location=%s driver=%s pci addr=%s\n",
414 pe->check_count, location,
415 eeh_driver_name(dev), eeh_pci_name(dev));
416 printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n",
417 eeh_driver_name(dev));
418 dump_stack();
419 }
420 goto dn_unlock;
421 }
422
423
424
425
426
427
428
429
430 ret = eeh_ops->get_state(pe, NULL);
431
432
433
434
435
436
437
438 if ((ret < 0) ||
439 (ret == EEH_STATE_NOT_SUPPORT) ||
440 (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) ==
441 (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) {
442 eeh_stats.false_positives++;
443 pe->false_positives++;
444 rc = 0;
445 goto dn_unlock;
446 }
447
448 eeh_stats.slot_resets++;
449
450
451
452
453
454 eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
455 eeh_serialize_unlock(flags);
456
457 eeh_send_failure_event(pe);
458
459
460
461
462
463 pr_err("EEH: Frozen PE#%x detected on PHB#%x\n",
464 pe->addr, pe->phb->global_number);
465 dump_stack();
466
467 return 1;
468
469dn_unlock:
470 eeh_serialize_unlock(flags);
471 return rc;
472}
473
474EXPORT_SYMBOL_GPL(eeh_dev_check_failure);
475
476
477
478
479
480
481
482
483
484
485
486
487
488unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
489{
490 unsigned long addr;
491 struct eeh_dev *edev;
492
493
494 addr = eeh_token_to_phys((unsigned long __force) token);
495 edev = eeh_addr_cache_get_dev(addr);
496 if (!edev) {
497 eeh_stats.no_device++;
498 return val;
499 }
500
501 eeh_dev_check_failure(edev);
502 return val;
503}
504
505EXPORT_SYMBOL(eeh_check_failure);
506
507
508
509
510
511
512
513
514
515
516int eeh_pci_enable(struct eeh_pe *pe, int function)
517{
518 int rc;
519
520 rc = eeh_ops->set_option(pe, function);
521 if (rc)
522 pr_warning("%s: Unexpected state change %d on PHB#%d-PE#%x, err=%d\n",
523 __func__, function, pe->phb->global_number, pe->addr, rc);
524
525 rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
526 if (rc > 0 && (rc & EEH_STATE_MMIO_ENABLED) &&
527 (function == EEH_OPT_THAW_MMIO))
528 return 0;
529
530 return rc;
531}
532
533
534
535
536
537
538
539
540
541int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
542{
543 struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);
544 struct eeh_pe *pe = edev->pe;
545
546 if (!pe) {
547 pr_err("%s: No PE found on PCI device %s\n",
548 __func__, pci_name(dev));
549 return -EINVAL;
550 }
551
552 switch (state) {
553 case pcie_deassert_reset:
554 eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
555 break;
556 case pcie_hot_reset:
557 eeh_ops->reset(pe, EEH_RESET_HOT);
558 break;
559 case pcie_warm_reset:
560 eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
561 break;
562 default:
563 return -EINVAL;
564 };
565
566 return 0;
567}
568
569
570
571
572
573
574
575
576
577
578
579static void *eeh_set_dev_freset(void *data, void *flag)
580{
581 struct pci_dev *dev;
582 unsigned int *freset = (unsigned int *)flag;
583 struct eeh_dev *edev = (struct eeh_dev *)data;
584
585 dev = eeh_dev_to_pci_dev(edev);
586 if (dev)
587 *freset |= dev->needs_freset;
588
589 return NULL;
590}
591
592
593
594
595
596
597
598static void eeh_reset_pe_once(struct eeh_pe *pe)
599{
600 unsigned int freset = 0;
601
602
603
604
605
606
607
608 eeh_pe_dev_traverse(pe, eeh_set_dev_freset, &freset);
609
610 if (freset)
611 eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
612 else
613 eeh_ops->reset(pe, EEH_RESET_HOT);
614
615
616
617
618#define PCI_BUS_RST_HOLD_TIME_MSEC 250
619 msleep(PCI_BUS_RST_HOLD_TIME_MSEC);
620
621
622
623
624
625 eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
626
627 eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
628
629
630
631
632
633#define PCI_BUS_SETTLE_TIME_MSEC 1800
634 msleep(PCI_BUS_SETTLE_TIME_MSEC);
635}
636
637
638
639
640
641
642
643
644
645int eeh_reset_pe(struct eeh_pe *pe)
646{
647 int flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
648 int i, rc;
649
650
651 for (i=0; i<3; i++) {
652 eeh_reset_pe_once(pe);
653
654 rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
655 if ((rc & flags) == flags)
656 return 0;
657
658 if (rc < 0) {
659 pr_err("%s: Unrecoverable slot failure on PHB#%d-PE#%x",
660 __func__, pe->phb->global_number, pe->addr);
661 return -1;
662 }
663 pr_err("EEH: bus reset %d failed on PHB#%d-PE#%x, rc=%d\n",
664 i+1, pe->phb->global_number, pe->addr, rc);
665 }
666
667 return -1;
668}
669
670
671
672
673
674
675
676
677
678
679void eeh_save_bars(struct eeh_dev *edev)
680{
681 int i;
682 struct device_node *dn;
683
684 if (!edev)
685 return;
686 dn = eeh_dev_to_of_node(edev);
687
688 for (i = 0; i < 16; i++)
689 eeh_ops->read_config(dn, i * 4, 4, &edev->config_space[i]);
690}
691
692
693
694
695
696
697
698
699
700int __init eeh_ops_register(struct eeh_ops *ops)
701{
702 if (!ops->name) {
703 pr_warning("%s: Invalid EEH ops name for %p\n",
704 __func__, ops);
705 return -EINVAL;
706 }
707
708 if (eeh_ops && eeh_ops != ops) {
709 pr_warning("%s: EEH ops of platform %s already existing (%s)\n",
710 __func__, eeh_ops->name, ops->name);
711 return -EEXIST;
712 }
713
714 eeh_ops = ops;
715
716 return 0;
717}
718
719
720
721
722
723
724
725
726int __exit eeh_ops_unregister(const char *name)
727{
728 if (!name || !strlen(name)) {
729 pr_warning("%s: Invalid EEH ops name\n",
730 __func__);
731 return -EINVAL;
732 }
733
734 if (eeh_ops && !strcmp(eeh_ops->name, name)) {
735 eeh_ops = NULL;
736 return 0;
737 }
738
739 return -EEXIST;
740}
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757int eeh_init(void)
758{
759 struct pci_controller *hose, *tmp;
760 struct device_node *phb;
761 static int cnt = 0;
762 int ret = 0;
763
764
765
766
767
768
769
770 if (machine_is(powernv) && cnt++ <= 0)
771 return ret;
772
773
774 if (!eeh_ops) {
775 pr_warning("%s: Platform EEH operation not found\n",
776 __func__);
777 return -EEXIST;
778 } else if ((ret = eeh_ops->init())) {
779 pr_warning("%s: Failed to call platform init function (%d)\n",
780 __func__, ret);
781 return ret;
782 }
783
784
785 ret = eeh_event_init();
786 if (ret)
787 return ret;
788
789
790 if (eeh_probe_mode_devtree()) {
791 list_for_each_entry_safe(hose, tmp,
792 &hose_list, list_node) {
793 phb = hose->dn;
794 traverse_pci_devices(phb, eeh_ops->of_probe, NULL);
795 }
796 } else if (eeh_probe_mode_dev()) {
797 list_for_each_entry_safe(hose, tmp,
798 &hose_list, list_node)
799 pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL);
800 } else {
801 pr_warning("%s: Invalid probe mode %d\n",
802 __func__, eeh_probe_mode);
803 return -EINVAL;
804 }
805
806
807
808
809
810
811 if (eeh_ops->post_init) {
812 ret = eeh_ops->post_init();
813 if (ret)
814 return ret;
815 }
816
817 if (eeh_subsystem_enabled)
818 pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
819 else
820 pr_warning("EEH: No capable adapters found\n");
821
822 return ret;
823}
824
825core_initcall_sync(eeh_init);
826
827
828
829
830
831
832
833
834
835
836
837
838
839void eeh_add_device_early(struct device_node *dn)
840{
841 struct pci_controller *phb;
842
843
844
845
846
847
848 if (!eeh_probe_mode_devtree())
849 return;
850
851 if (!of_node_to_eeh_dev(dn))
852 return;
853 phb = of_node_to_eeh_dev(dn)->phb;
854
855
856 if (NULL == phb || 0 == phb->buid)
857 return;
858
859 eeh_ops->of_probe(dn, NULL);
860}
861
862
863
864
865
866
867
868
869
870void eeh_add_device_tree_early(struct device_node *dn)
871{
872 struct device_node *sib;
873
874 for_each_child_of_node(dn, sib)
875 eeh_add_device_tree_early(sib);
876 eeh_add_device_early(dn);
877}
878EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
879
880
881
882
883
884
885
886
887void eeh_add_device_late(struct pci_dev *dev)
888{
889 struct device_node *dn;
890 struct eeh_dev *edev;
891
892 if (!dev || !eeh_subsystem_enabled)
893 return;
894
895 pr_debug("EEH: Adding device %s\n", pci_name(dev));
896
897 dn = pci_device_to_OF_node(dev);
898 edev = of_node_to_eeh_dev(dn);
899 if (edev->pdev == dev) {
900 pr_debug("EEH: Already referenced !\n");
901 return;
902 }
903
904
905
906
907
908
909
910 if (edev->pdev) {
911 eeh_rmv_from_parent_pe(edev);
912 eeh_addr_cache_rmv_dev(edev->pdev);
913 eeh_sysfs_remove_device(edev->pdev);
914 edev->mode &= ~EEH_DEV_SYSFS;
915
916 edev->pdev = NULL;
917 dev->dev.archdata.edev = NULL;
918 }
919
920 edev->pdev = dev;
921 dev->dev.archdata.edev = edev;
922
923
924
925
926
927 if (eeh_probe_mode_dev())
928 eeh_ops->dev_probe(dev, NULL);
929
930 eeh_addr_cache_insert_dev(dev);
931}
932
933
934
935
936
937
938
939
940
941void eeh_add_device_tree_late(struct pci_bus *bus)
942{
943 struct pci_dev *dev;
944
945 list_for_each_entry(dev, &bus->devices, bus_list) {
946 eeh_add_device_late(dev);
947 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
948 struct pci_bus *subbus = dev->subordinate;
949 if (subbus)
950 eeh_add_device_tree_late(subbus);
951 }
952 }
953}
954EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
955
956
957
958
959
960
961
962
963
964void eeh_add_sysfs_files(struct pci_bus *bus)
965{
966 struct pci_dev *dev;
967
968 list_for_each_entry(dev, &bus->devices, bus_list) {
969 eeh_sysfs_add_device(dev);
970 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
971 struct pci_bus *subbus = dev->subordinate;
972 if (subbus)
973 eeh_add_sysfs_files(subbus);
974 }
975 }
976}
977EXPORT_SYMBOL_GPL(eeh_add_sysfs_files);
978
979
980
981
982
983
984
985
986
987
988
989void eeh_remove_device(struct pci_dev *dev)
990{
991 struct eeh_dev *edev;
992
993 if (!dev || !eeh_subsystem_enabled)
994 return;
995 edev = pci_dev_to_eeh_dev(dev);
996
997
998 pr_debug("EEH: Removing device %s\n", pci_name(dev));
999
1000 if (!edev || !edev->pdev || !edev->pe) {
1001 pr_debug("EEH: Not referenced !\n");
1002 return;
1003 }
1004
1005
1006
1007
1008
1009
1010
1011 edev->pdev = NULL;
1012 dev->dev.archdata.edev = NULL;
1013 if (!(edev->pe->state & EEH_PE_KEEP))
1014 eeh_rmv_from_parent_pe(edev);
1015 else
1016 edev->mode |= EEH_DEV_DISCONNECTED;
1017
1018 eeh_addr_cache_rmv_dev(dev);
1019 eeh_sysfs_remove_device(dev);
1020 edev->mode &= ~EEH_DEV_SYSFS;
1021}
1022
1023static int proc_eeh_show(struct seq_file *m, void *v)
1024{
1025 if (0 == eeh_subsystem_enabled) {
1026 seq_printf(m, "EEH Subsystem is globally disabled\n");
1027 seq_printf(m, "eeh_total_mmio_ffs=%llu\n", eeh_stats.total_mmio_ffs);
1028 } else {
1029 seq_printf(m, "EEH Subsystem is enabled\n");
1030 seq_printf(m,
1031 "no device=%llu\n"
1032 "no device node=%llu\n"
1033 "no config address=%llu\n"
1034 "check not wanted=%llu\n"
1035 "eeh_total_mmio_ffs=%llu\n"
1036 "eeh_false_positives=%llu\n"
1037 "eeh_slot_resets=%llu\n",
1038 eeh_stats.no_device,
1039 eeh_stats.no_dn,
1040 eeh_stats.no_cfg_addr,
1041 eeh_stats.ignored_check,
1042 eeh_stats.total_mmio_ffs,
1043 eeh_stats.false_positives,
1044 eeh_stats.slot_resets);
1045 }
1046
1047 return 0;
1048}
1049
1050static int proc_eeh_open(struct inode *inode, struct file *file)
1051{
1052 return single_open(file, proc_eeh_show, NULL);
1053}
1054
1055static const struct file_operations proc_eeh_operations = {
1056 .open = proc_eeh_open,
1057 .read = seq_read,
1058 .llseek = seq_lseek,
1059 .release = single_release,
1060};
1061
1062static int __init eeh_init_proc(void)
1063{
1064 if (machine_is(pseries) || machine_is(powernv))
1065 proc_create("powerpc/eeh", 0, NULL, &proc_eeh_operations);
1066 return 0;
1067}
1068__initcall(eeh_init_proc);
1069