Skip to content

Commit 91b9904

Browse files
Dave JiangLinus Torvalds
authored andcommitted
drivers/edac: updated PCI monitoring
Moving PCI to a per-instance device model This should include the correct sysfs setup as well. Please review. Signed-off-by: Dave Jiang <[email protected]> Signed-off-by: Douglas Thompson <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 81d87cb commit 91b9904

File tree

7 files changed

+861
-65
lines changed

7 files changed

+861
-65
lines changed

drivers/edac/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@ obj-$(CONFIG_EDAC) := edac_stub.o
1111
obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
1212

1313
edac_core-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
14-
1514
edac_core-objs += edac_module.o edac_device_sysfs.o
1615

16+
ifdef CONFIG_PCI
17+
edac_core-objs += edac_pci.o edac_pci_sysfs.o
18+
endif
19+
1720
obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
1821
obj-$(CONFIG_EDAC_I5000) += i5000_edac.o
1922
obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o

drivers/edac/e752x_edac.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
static int force_function_unhide;
3232

33+
static struct edac_pci_ctl_info *e752x_pci;
34+
3335
#define e752x_printk(level, fmt, arg...) \
3436
edac_printk(level, "e752x", fmt, ##arg)
3537

@@ -1040,6 +1042,17 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
10401042
e752x_init_error_reporting_regs(pvt);
10411043
e752x_get_error_info(mci, &discard); /* clear other MCH errors */
10421044

1045+
/* allocating generic PCI control info */
1046+
e752x_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
1047+
if (!e752x_pci) {
1048+
printk(KERN_WARNING
1049+
"%s(): Unable to create PCI control\n",
1050+
__func__);
1051+
printk(KERN_WARNING
1052+
"%s(): PCI error report via EDAC not setup\n",
1053+
__func__);
1054+
}
1055+
10431056
/* get this far and it's successful */
10441057
debugf3("%s(): success\n", __func__);
10451058
return 0;
@@ -1073,6 +1086,9 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev)
10731086

10741087
debugf0("%s()\n", __func__);
10751088

1089+
if (e752x_pci)
1090+
edac_pci_release_generic_ctl(e752x_pci);
1091+
10761092
if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
10771093
return;
10781094

drivers/edac/edac_core.h

Lines changed: 114 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@
6060
#define edac_device_printk(ctl, level, fmt, arg...) \
6161
printk(level "EDAC DEVICE%d: " fmt, ctl->dev_idx, ##arg)
6262

63+
/* edac_pci printk */
64+
#define edac_pci_printk(ctl, level, fmt, arg...) \
65+
printk(level "EDAC PCI%d: " fmt, ctl->pci_idx, ##arg)
66+
6367
/* prefixes for edac_printk() and edac_mc_printk() */
6468
#define EDAC_MC "MC"
6569
#define EDAC_PCI "PCI"
@@ -200,6 +204,13 @@ enum scrub_type {
200204

201205
/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
202206

207+
/* EDAC internal operation states */
208+
#define OP_ALLOC 0x100
209+
#define OP_RUNNING_POLL 0x201
210+
#define OP_RUNNING_INTERRUPT 0x202
211+
#define OP_RUNNING_POLL_INTR 0x203
212+
#define OP_OFFLINE 0x300
213+
203214
extern char * edac_align_ptr(void *ptr, unsigned size);
204215

205216
/*
@@ -520,12 +531,6 @@ struct edac_device_ctl_info {
520531

521532
/* the internal state of this controller instance */
522533
int op_state;
523-
#define OP_ALLOC 0x100
524-
#define OP_RUNNING_POLL 0x201
525-
#define OP_RUNNING_INTERRUPT 0x202
526-
#define OP_RUNNING_POLL_INTR 0x203
527-
#define OP_OFFLINE 0x300
528-
529534
/* work struct for this instance */
530535
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
531536
struct delayed_work work;
@@ -626,6 +631,84 @@ extern void edac_device_free_ctl_info( struct edac_device_ctl_info *ctl_info);
626631

627632
#ifdef CONFIG_PCI
628633

634+
struct edac_pci_counter {
635+
atomic_t pe_count;
636+
atomic_t npe_count;
637+
};
638+
639+
/*
640+
* Abstract edac_pci control info structure
641+
*
642+
*/
643+
struct edac_pci_ctl_info {
644+
/* for global list of edac_pci_ctl_info structs */
645+
struct list_head link;
646+
647+
int pci_idx;
648+
649+
/* Per instance controls for this edac_device */
650+
int check_parity_error; /* boolean for checking parity errs */
651+
int log_parity_error; /* boolean for logging parity errs */
652+
int panic_on_pe; /* boolean for panic'ing on a PE */
653+
unsigned poll_msec; /* number of milliseconds to poll interval */
654+
unsigned long delay; /* number of jiffies for poll_msec */
655+
656+
struct sysdev_class *edac_class; /* pointer to class */
657+
658+
/* the internal state of this controller instance */
659+
int op_state;
660+
/* work struct for this instance */
661+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
662+
struct delayed_work work;
663+
#else
664+
struct work_struct work;
665+
#endif
666+
667+
/* pointer to edac polling checking routine:
668+
* If NOT NULL: points to polling check routine
669+
* If NULL: Then assumes INTERRUPT operation, where
670+
* MC driver will receive events
671+
*/
672+
void (*edac_check) (struct edac_pci_ctl_info * edac_dev);
673+
674+
struct device *dev; /* pointer to device structure */
675+
676+
const char *mod_name; /* module name */
677+
const char *ctl_name; /* edac controller name */
678+
const char *dev_name; /* pci/platform/etc... name */
679+
680+
void *pvt_info; /* pointer to 'private driver' info */
681+
682+
unsigned long start_time;/* edac_pci load start time (jiffies)*/
683+
684+
/* these are for safe removal of devices from global list while
685+
* NMI handlers may be traversing list
686+
*/
687+
struct rcu_head rcu;
688+
struct completion complete;
689+
690+
/* sysfs top name under 'edac' directory
691+
* and instance name:
692+
* cpu/cpu0/...
693+
* cpu/cpu1/...
694+
* cpu/cpu2/...
695+
* ...
696+
*/
697+
char name[EDAC_DEVICE_NAME_LEN + 1];
698+
699+
/* Event counters for the this whole EDAC Device */
700+
struct edac_pci_counter counters;
701+
702+
/* edac sysfs device control for the 'name'
703+
* device this structure controls
704+
*/
705+
struct kobject kobj;
706+
struct completion kobj_complete;
707+
};
708+
709+
#define to_edac_pci_ctl_work(w) \
710+
container_of(w, struct edac_pci_ctl_info,work)
711+
629712
/* write all or some bits in a byte-register*/
630713
static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,
631714
u8 mask)
@@ -726,5 +809,30 @@ extern void edac_device_handle_ue(struct edac_device_ctl_info *edac_dev,
726809
extern void edac_device_handle_ce(struct edac_device_ctl_info *edac_dev,
727810
int inst_nr, int block_nr, const char *msg);
728811

812+
/*
813+
* edac_pci APIs
814+
*/
815+
extern struct edac_pci_ctl_info *
816+
edac_pci_alloc_ctl_info(unsigned int sz_pvt, const char *edac_pci_name);
817+
818+
extern void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci);
819+
820+
extern void
821+
edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci, unsigned long value);
822+
823+
extern int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx);
824+
extern struct edac_pci_ctl_info * edac_pci_del_device(struct device *dev);
825+
826+
extern struct edac_pci_ctl_info *
827+
edac_pci_create_generic_ctl(struct device *dev, const char *mod_name);
828+
829+
extern void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci);
830+
extern int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci);
831+
extern void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci);
832+
833+
/*
834+
* edac misc APIs
835+
*/
836+
extern char * edac_op_state_toString(int op_state);
729837

730838
#endif /* _EDAC_CORE_H_ */

drivers/edac/edac_device.c

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -418,27 +418,6 @@ void edac_device_reset_delay_period(
418418
unlock_device_list();
419419
}
420420

421-
/*
422-
* edac_op_state_toString(edac_dev)
423-
*/
424-
static char *edac_op_state_toString(struct edac_device_ctl_info *edac_dev)
425-
{
426-
int opstate = edac_dev->op_state;
427-
428-
if (opstate == OP_RUNNING_POLL)
429-
return "POLLED";
430-
else if (opstate == OP_RUNNING_INTERRUPT)
431-
return "INTERRUPT";
432-
else if (opstate == OP_RUNNING_POLL_INTR)
433-
return "POLL-INTR";
434-
else if (opstate == OP_ALLOC)
435-
return "ALLOC";
436-
else if (opstate == OP_OFFLINE)
437-
return "OFFLINE";
438-
439-
return "UNKNOWN";
440-
}
441-
442421
/**
443422
* edac_device_add_device: Insert the 'edac_dev' structure into the
444423
* edac_device global list and create sysfs entries associated with
@@ -496,7 +475,7 @@ int edac_device_add_device(struct edac_device_ctl_info *edac_dev, int edac_idx)
496475
edac_dev->mod_name,
497476
edac_dev->ctl_name,
498477
dev_name(edac_dev),
499-
edac_op_state_toString(edac_dev)
478+
edac_op_state_toString(edac_dev->op_state)
500479
);
501480

502481
unlock_device_list();

drivers/edac/edac_module.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,25 @@ static struct sysdev_class edac_class = {
3434
};
3535
static int edac_class_valid = 0;
3636

37+
/*
38+
* edac_op_state_toString()
39+
*/
40+
char * edac_op_state_toString(int opstate)
41+
{
42+
if (opstate == OP_RUNNING_POLL)
43+
return "POLLED";
44+
else if (opstate == OP_RUNNING_INTERRUPT)
45+
return "INTERRUPT";
46+
else if (opstate == OP_RUNNING_POLL_INTR)
47+
return "POLL-INTR";
48+
else if (opstate == OP_ALLOC)
49+
return "ALLOC";
50+
else if (opstate == OP_OFFLINE)
51+
return "OFFLINE";
52+
53+
return "UNKNOWN";
54+
}
55+
3756
/*
3857
* edac_get_edac_class()
3958
*
@@ -153,26 +172,16 @@ static int __init edac_init(void)
153172
goto error_sysfs;
154173
}
155174

156-
/* Create the PCI parity sysfs entries */
157-
if (edac_sysfs_pci_setup()) {
158-
edac_printk(KERN_ERR, EDAC_MC,
159-
"PCI: Error initializing sysfs code\n");
160-
err = -ENODEV;
161-
goto error_mem;
162-
}
163-
164175
/* Setup/Initialize the edac_device system */
165176
err = edac_workqueue_setup();
166177
if (err) {
167178
edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
168-
goto error_pci;
179+
goto error_mem;
169180
}
170181

171182
return 0;
172183

173184
/* Error teardown stack */
174-
error_pci:
175-
edac_sysfs_pci_teardown();
176185
error_mem:
177186
edac_sysfs_memctrl_teardown();
178187
error_sysfs:
@@ -192,7 +201,6 @@ static void __exit edac_exit(void)
192201
/* tear down the various subsystems*/
193202
edac_workqueue_teardown();
194203
edac_sysfs_memctrl_teardown();
195-
edac_sysfs_pci_teardown();
196204
edac_unregister_sysfs_edac_name();
197205
}
198206

0 commit comments

Comments
 (0)