1e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
2fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers * file for managing the edac_device subsystem of devices for EDAC
3e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *
4631dd1a885b6d7e9f6f51b4e5b311c2bb04c323cJustin P. Mattock * (C) 2007 SoftwareBitMaker
51c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *
6e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * This file may be distributed under the terms of the
7e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * GNU General Public License.
8e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *
9e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * Written Doug Thompson <norsk5@xmission.com>
10e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *
11e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
12e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
13e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#include <linux/ctype.h>
141c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson#include <linux/module.h>
155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
1630e1f7a8122145f44f45c95366e27b6bb0b08428Borislav Petkov#include <linux/edac.h>
17e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
18e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#include "edac_core.h"
19e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#include "edac_module.h"
20e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
21e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define EDAC_DEVICE_SYMLINK	"device"
22e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
23e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define to_edacdev(k) container_of(k, struct edac_device_ctl_info, kobj)
24e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define to_edacdev_attr(a) container_of(a, struct edacdev_attribute, attr)
25e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
26e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
27e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
28e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * Set of edac_device_ctl_info attribute store/show functions
29e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
30e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
31e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* 'log_ue' */
32079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t edac_device_ctl_log_ue_show(struct edac_device_ctl_info
33052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson					*ctl_info, char *data)
34e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
35079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return sprintf(data, "%u\n", ctl_info->log_ue);
36e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
37e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
38079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t edac_device_ctl_log_ue_store(struct edac_device_ctl_info
39052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson					*ctl_info, const char *data,
40052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson					size_t count)
41e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
42e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* if parameter is zero, turn off flag, if non-zero turn on flag */
43079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	ctl_info->log_ue = (simple_strtoul(data, NULL, 0) != 0);
44e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
45079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return count;
46e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
47e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
48e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* 'log_ce' */
49079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t edac_device_ctl_log_ce_show(struct edac_device_ctl_info
50052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson					*ctl_info, char *data)
51e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
52079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return sprintf(data, "%u\n", ctl_info->log_ce);
53e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
54e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
55079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t edac_device_ctl_log_ce_store(struct edac_device_ctl_info
56052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson					*ctl_info, const char *data,
57052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson					size_t count)
58e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
59e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* if parameter is zero, turn off flag, if non-zero turn on flag */
60079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	ctl_info->log_ce = (simple_strtoul(data, NULL, 0) != 0);
61e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
62079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return count;
63e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
64e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
65e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* 'panic_on_ue' */
66079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t edac_device_ctl_panic_on_ue_show(struct edac_device_ctl_info
67079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson						*ctl_info, char *data)
68e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
69079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return sprintf(data, "%u\n", ctl_info->panic_on_ue);
70e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
71e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
72079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t edac_device_ctl_panic_on_ue_store(struct edac_device_ctl_info
73079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson						 *ctl_info, const char *data,
74079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson						 size_t count)
75e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
76e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* if parameter is zero, turn off flag, if non-zero turn on flag */
77079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	ctl_info->panic_on_ue = (simple_strtoul(data, NULL, 0) != 0);
78e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
79e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	return count;
80e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
81e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
82e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* 'poll_msec' show and store functions*/
83079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t edac_device_ctl_poll_msec_show(struct edac_device_ctl_info
84052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson					*ctl_info, char *data)
85e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
86079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return sprintf(data, "%u\n", ctl_info->poll_msec);
87e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
88e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
89079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t edac_device_ctl_poll_msec_store(struct edac_device_ctl_info
90052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson					*ctl_info, const char *data,
91052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson					size_t count)
92e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
93e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	unsigned long value;
94e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
95e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* get the value and enforce that it is non-zero, must be at least
96e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	 * one millisecond for the delay period, between scans
97e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	 * Then cancel last outstanding delay for the work request
98e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	 * and set a new one.
99e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	 */
100079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	value = simple_strtoul(data, NULL, 0);
101079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	edac_device_reset_delay_period(ctl_info, value);
102e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
103079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return count;
104e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
105e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
106e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* edac_device_ctl_info specific attribute structure */
107e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstruct ctl_info_attribute {
108079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct attribute attr;
1091c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	ssize_t(*show) (struct edac_device_ctl_info *, char *);
1101c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	ssize_t(*store) (struct edac_device_ctl_info *, const char *, size_t);
111e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
112e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
113e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define to_ctl_info(k) container_of(k, struct edac_device_ctl_info, kobj)
114e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define to_ctl_info_attr(a) container_of(a,struct ctl_info_attribute,attr)
115e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
116e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* Function to 'show' fields from the edac_dev 'ctl_info' structure */
117e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic ssize_t edac_dev_ctl_info_show(struct kobject *kobj,
118052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				struct attribute *attr, char *buffer)
119e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
120079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
121079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
122e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
123079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	if (ctl_info_attr->show)
124079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson		return ctl_info_attr->show(edac_dev, buffer);
125079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return -EIO;
126e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
127e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
128e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* Function to 'store' fields into the edac_dev 'ctl_info' structure */
129e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic ssize_t edac_dev_ctl_info_store(struct kobject *kobj,
130052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				struct attribute *attr,
131052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				const char *buffer, size_t count)
132e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
133079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
134079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
135e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
136079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	if (ctl_info_attr->store)
137079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson		return ctl_info_attr->store(edac_dev, buffer, count);
138079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return -EIO;
139e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
140e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
141e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* edac_dev file operations for an 'ctl_info' */
14252cf25d0ab7f78eeecc59ac652ed5090f69b619eEmese Revfystatic const struct sysfs_ops device_ctl_info_ops = {
143079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	.show = edac_dev_ctl_info_show,
144079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	.store = edac_dev_ctl_info_store
145e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
146e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
147e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define CTL_INFO_ATTR(_name,_mode,_show,_store)        \
148e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic struct ctl_info_attribute attr_ctl_info_##_name = {      \
149052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	.attr = {.name = __stringify(_name), .mode = _mode },   \
150052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	.show   = _show,                                        \
151052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	.store  = _store,                                       \
152e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
153e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
154e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* Declare the various ctl_info attributes here and their respective ops */
155079708b9173595bf74b31b14c36e946359ae6c7eDouglas ThompsonCTL_INFO_ATTR(log_ue, S_IRUGO | S_IWUSR,
156052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	edac_device_ctl_log_ue_show, edac_device_ctl_log_ue_store);
157079708b9173595bf74b31b14c36e946359ae6c7eDouglas ThompsonCTL_INFO_ATTR(log_ce, S_IRUGO | S_IWUSR,
158052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	edac_device_ctl_log_ce_show, edac_device_ctl_log_ce_store);
159079708b9173595bf74b31b14c36e946359ae6c7eDouglas ThompsonCTL_INFO_ATTR(panic_on_ue, S_IRUGO | S_IWUSR,
160052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	edac_device_ctl_panic_on_ue_show,
161052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	edac_device_ctl_panic_on_ue_store);
162079708b9173595bf74b31b14c36e946359ae6c7eDouglas ThompsonCTL_INFO_ATTR(poll_msec, S_IRUGO | S_IWUSR,
163052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	edac_device_ctl_poll_msec_show, edac_device_ctl_poll_msec_store);
164e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
165e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* Base Attributes of the EDAC_DEVICE ECC object */
166e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic struct ctl_info_attribute *device_ctrl_attr[] = {
167e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	&attr_ctl_info_panic_on_ue,
168e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	&attr_ctl_info_log_ue,
169e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	&attr_ctl_info_log_ce,
170e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	&attr_ctl_info_poll_msec,
171e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	NULL,
172e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
173e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
1741c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson/*
1751c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * edac_device_ctrl_master_release
1761c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *
1771c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *	called when the reference count for the 'main' kobj
1781c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *	for a edac_device control struct reaches zero
1791c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *
1801c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *	Reference count model:
1811c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		One 'main' kobject for each control structure allocated.
1821c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		That main kobj is initially set to one AND
1831c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		the reference count for the EDAC 'core' module is
1841c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		bumped by one, thus added 'keep in memory' dependency.
1851c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *
1861c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		Each new internal kobj (in instances and blocks) then
1871c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		bumps the 'main' kobject.
1881c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *
1891c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		When they are released their release functions decrement
1901c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		the 'main' kobj.
1911c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *
1921c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		When the main kobj reaches zero (0) then THIS function
1931c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		is called which then decrements the EDAC 'core' module.
1941c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		When the module reference count reaches zero then the
1951c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		module no longer has dependency on keeping the release
1961c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		function code in memory and module can be unloaded.
1971c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *
1981c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		This will support several control objects as well, each
1991c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *		with its own 'main' kobj.
2001c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson */
201e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic void edac_device_ctrl_master_release(struct kobject *kobj)
202e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
2031c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	struct edac_device_ctl_info *edac_dev = to_edacdev(kobj);
204e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
205b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	debugf4("%s() control index=%d\n", __func__, edac_dev->dev_idx);
206e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
2071c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* decrement the EDAC CORE module ref count */
2081c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	module_put(edac_dev->owner);
2091c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
2101c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* free the control struct containing the 'main' kobj
2111c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * passed in to this routine
2121c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
2131c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	kfree(edac_dev);
214e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
215e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
2161c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson/* ktype for the main (master) kobject */
217e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic struct kobj_type ktype_device_ctrl = {
218e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	.release = edac_device_ctrl_master_release,
219e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	.sysfs_ops = &device_ctl_info_ops,
220079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	.default_attrs = (struct attribute **)device_ctrl_attr,
221e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
222e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
223e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
2241c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * edac_device_register_sysfs_main_kobj
225e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *
226e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	perform the high level setup for the new edac_device instance
227e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *
228e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * Return:  0 SUCCESS
229e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *         !0 FAILURE
230e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
2311c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonint edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
232e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
233fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers	struct bus_type *edac_subsys;
2341c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	int err;
235e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
236e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	debugf1("%s()\n", __func__);
237e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
238079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	/* get the /sys/devices/system/edac reference */
239fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers	edac_subsys = edac_get_sysfs_subsys();
240fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers	if (edac_subsys == NULL) {
241fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers		debugf1("%s() no edac_subsys error\n", __func__);
2421c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		err = -ENODEV;
2431c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		goto err_out;
244079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	}
245e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
246fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers	/* Point to the 'edac_subsys' this instance 'reports' to */
247fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers	edac_dev->edac_subsys = edac_subsys;
248e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
249e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* Init the devices's kobject */
250079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	memset(&edac_dev->kobj, 0, sizeof(struct kobject));
2511c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
2521c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* Record which module 'owns' this control structure
2531c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * and bump the ref count of the module
2541c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
2551c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	edac_dev->owner = THIS_MODULE;
2561c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
2571c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	if (!try_module_get(edac_dev->owner)) {
2581c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		err = -ENODEV;
25930e1f7a8122145f44f45c95366e27b6bb0b08428Borislav Petkov		goto err_mod_get;
2601c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	}
2611c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
2621c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* register */
263b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman	err = kobject_init_and_add(&edac_dev->kobj, &ktype_device_ctrl,
264fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers				   &edac_subsys->dev_root->kobj,
265b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman				   "%s", edac_dev->name);
266e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	if (err) {
267e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson		debugf1("%s()Failed to register '.../edac/%s'\n",
268079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson			__func__, edac_dev->name);
2691c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		goto err_kobj_reg;
270e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	}
271b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman	kobject_uevent(&edac_dev->kobj, KOBJ_ADD);
272e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
2731c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* At this point, to 'free' the control struct,
2741c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * edac_device_unregister_sysfs_main_kobj() must be used
2751c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
2761c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
277b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	debugf4("%s() Registered '.../edac/%s' kobject\n",
278e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson		__func__, edac_dev->name);
279e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
280e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	return 0;
2811c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
2821c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* Error exit stack */
2831c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonerr_kobj_reg:
2841c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	module_put(edac_dev->owner);
2851c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
28630e1f7a8122145f44f45c95366e27b6bb0b08428Borislav Petkoverr_mod_get:
287fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers	edac_put_sysfs_subsys();
28830e1f7a8122145f44f45c95366e27b6bb0b08428Borislav Petkov
2891c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonerr_out:
2901c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	return err;
291e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
292e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
293e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
2941c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * edac_device_unregister_sysfs_main_kobj:
295e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	the '..../edac/<name>' kobject
296e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
29730e1f7a8122145f44f45c95366e27b6bb0b08428Borislav Petkovvoid edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
298e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
299e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	debugf0("%s()\n", __func__);
300b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	debugf4("%s() name of kobject is: %s\n",
30130e1f7a8122145f44f45c95366e27b6bb0b08428Borislav Petkov		__func__, kobject_name(&dev->kobj));
302e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
303e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/*
304e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	 * Unregister the edac device's kobject and
3051c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * allow for reference count to reach 0 at which point
3061c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * the callback will be called to:
3071c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 *   a) module_put() this module
3081c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 *   b) 'kfree' the memory
309e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	 */
31030e1f7a8122145f44f45c95366e27b6bb0b08428Borislav Petkov	kobject_put(&dev->kobj);
311fe5ff8b84c8b03348a2f64ea9d884348faec2217Kay Sievers	edac_put_sysfs_subsys();
312e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
313e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
3141c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson/* edac_dev -> instance information */
315e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
316e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
317e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * Set of low-level instance attribute show functions
318e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
319079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t instance_ue_count_show(struct edac_device_instance *instance,
320052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				char *data)
321e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
322079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return sprintf(data, "%u\n", instance->counters.ue_count);
323e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
324e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
325079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic ssize_t instance_ce_count_show(struct edac_device_instance *instance,
326052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				char *data)
327e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
328079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return sprintf(data, "%u\n", instance->counters.ce_count);
329e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
330e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
331e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define to_instance(k) container_of(k, struct edac_device_instance, kobj)
332e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define to_instance_attr(a) container_of(a,struct instance_attribute,attr)
333e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
334e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* DEVICE instance kobject release() function */
335e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic void edac_device_ctrl_instance_release(struct kobject *kobj)
336e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
337e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	struct edac_device_instance *instance;
338e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
339e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	debugf1("%s()\n", __func__);
340e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
3411c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* map from this kobj to the main control struct
3421c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * and then dec the main kobj count
3431c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
344e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	instance = to_instance(kobj);
3451c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	kobject_put(&instance->ctl->kobj);
346e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
347e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
348e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* instance specific attribute structure */
349e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstruct instance_attribute {
350079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct attribute attr;
35152490c8d07680a7ecc3c1a70a16841455d37e96aDouglas Thompson	ssize_t(*show) (struct edac_device_instance *, char *);
35252490c8d07680a7ecc3c1a70a16841455d37e96aDouglas Thompson	ssize_t(*store) (struct edac_device_instance *, const char *, size_t);
353e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
354e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
355e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* Function to 'show' fields from the edac_dev 'instance' structure */
356e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic ssize_t edac_dev_instance_show(struct kobject *kobj,
357052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				struct attribute *attr, char *buffer)
358e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
359079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct edac_device_instance *instance = to_instance(kobj);
360079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct instance_attribute *instance_attr = to_instance_attr(attr);
361e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
362079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	if (instance_attr->show)
363079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson		return instance_attr->show(instance, buffer);
364079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return -EIO;
365e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
366e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
367e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* Function to 'store' fields into the edac_dev 'instance' structure */
368e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic ssize_t edac_dev_instance_store(struct kobject *kobj,
369052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				struct attribute *attr,
370052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				const char *buffer, size_t count)
371e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
372079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct edac_device_instance *instance = to_instance(kobj);
373079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct instance_attribute *instance_attr = to_instance_attr(attr);
374e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
375079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	if (instance_attr->store)
376079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson		return instance_attr->store(instance, buffer, count);
377079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return -EIO;
378e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
379e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
380e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* edac_dev file operations for an 'instance' */
38152cf25d0ab7f78eeecc59ac652ed5090f69b619eEmese Revfystatic const struct sysfs_ops device_instance_ops = {
382079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	.show = edac_dev_instance_show,
383079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	.store = edac_dev_instance_store
384e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
385e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
386e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define INSTANCE_ATTR(_name,_mode,_show,_store)        \
387e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic struct instance_attribute attr_instance_##_name = {      \
388052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	.attr = {.name = __stringify(_name), .mode = _mode },   \
389052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	.show   = _show,                                        \
390052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	.store  = _store,                                       \
391e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
392e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
393e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
394e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * Define attributes visible for the edac_device instance object
395e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	Each contains a pointer to a show and an optional set
396e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	function pointer that does the low level output/input
397e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
398079708b9173595bf74b31b14c36e946359ae6c7eDouglas ThompsonINSTANCE_ATTR(ce_count, S_IRUGO, instance_ce_count_show, NULL);
399079708b9173595bf74b31b14c36e946359ae6c7eDouglas ThompsonINSTANCE_ATTR(ue_count, S_IRUGO, instance_ue_count_show, NULL);
400e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
401e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* list of edac_dev 'instance' attributes */
402e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic struct instance_attribute *device_instance_attr[] = {
403e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	&attr_instance_ce_count,
404e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	&attr_instance_ue_count,
405e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	NULL,
406e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
407e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
408e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* The 'ktype' for each edac_dev 'instance' */
409e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic struct kobj_type ktype_instance_ctrl = {
410e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	.release = edac_device_ctrl_instance_release,
411e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	.sysfs_ops = &device_instance_ops,
412079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	.default_attrs = (struct attribute **)device_instance_attr,
413e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
414e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
4151c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson/* edac_dev -> instance -> block information */
416e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
417b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson#define to_block(k) container_of(k, struct edac_device_block, kobj)
418b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson#define to_block_attr(a) \
419b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	container_of(a, struct edac_dev_sysfs_block_attribute, attr)
420b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson
421e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
422e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * Set of low-level block attribute show functions
423e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
424b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompsonstatic ssize_t block_ue_count_show(struct kobject *kobj,
425b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson					struct attribute *attr, char *data)
426e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
427b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	struct edac_device_block *block = to_block(kobj);
428b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson
429079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return sprintf(data, "%u\n", block->counters.ue_count);
430e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
431e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
432b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompsonstatic ssize_t block_ce_count_show(struct kobject *kobj,
433b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson					struct attribute *attr, char *data)
434e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
435b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	struct edac_device_block *block = to_block(kobj);
436b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson
437079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return sprintf(data, "%u\n", block->counters.ce_count);
438e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
439e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
440e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* DEVICE block kobject release() function */
441e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic void edac_device_ctrl_block_release(struct kobject *kobj)
442e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
443e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	struct edac_device_block *block;
444e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
445e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	debugf1("%s()\n", __func__);
446e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
4471c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* get the container of the kobj */
448e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	block = to_block(kobj);
4491c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
4501c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* map from 'block kobj' to 'block->instance->controller->main_kobj'
4511c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * now 'release' the block kobject
4521c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
4531c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	kobject_put(&block->instance->ctl->kobj);
454e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
455e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
456e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
457e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* Function to 'show' fields from the edac_dev 'block' structure */
458e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic ssize_t edac_dev_block_show(struct kobject *kobj,
459052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				struct attribute *attr, char *buffer)
460e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
461b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	struct edac_dev_sysfs_block_attribute *block_attr =
462b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson						to_block_attr(attr);
463e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
464079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	if (block_attr->show)
465b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson		return block_attr->show(kobj, attr, buffer);
466079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return -EIO;
467e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
468e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
469e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* Function to 'store' fields into the edac_dev 'block' structure */
470e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic ssize_t edac_dev_block_store(struct kobject *kobj,
471052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				struct attribute *attr,
472052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				const char *buffer, size_t count)
473e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
474b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	struct edac_dev_sysfs_block_attribute *block_attr;
475b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson
476b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	block_attr = to_block_attr(attr);
477e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
478079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	if (block_attr->store)
479b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson		return block_attr->store(kobj, attr, buffer, count);
480079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	return -EIO;
481e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
482e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
483e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* edac_dev file operations for a 'block' */
48452cf25d0ab7f78eeecc59ac652ed5090f69b619eEmese Revfystatic const struct sysfs_ops device_block_ops = {
485079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	.show = edac_dev_block_show,
486079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	.store = edac_dev_block_store
487e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
488e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
489e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson#define BLOCK_ATTR(_name,_mode,_show,_store)        \
490b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompsonstatic struct edac_dev_sysfs_block_attribute attr_block_##_name = {	\
491052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	.attr = {.name = __stringify(_name), .mode = _mode },   \
492052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	.show   = _show,                                        \
493052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	.store  = _store,                                       \
494e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
495e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
496079708b9173595bf74b31b14c36e946359ae6c7eDouglas ThompsonBLOCK_ATTR(ce_count, S_IRUGO, block_ce_count_show, NULL);
497079708b9173595bf74b31b14c36e946359ae6c7eDouglas ThompsonBLOCK_ATTR(ue_count, S_IRUGO, block_ue_count_show, NULL);
498e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
499e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* list of edac_dev 'block' attributes */
500b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompsonstatic struct edac_dev_sysfs_block_attribute *device_block_attr[] = {
501e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	&attr_block_ce_count,
502e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	&attr_block_ue_count,
503e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	NULL,
504e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
505e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
506e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/* The 'ktype' for each edac_dev 'block' */
507e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic struct kobj_type ktype_block_ctrl = {
508e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	.release = edac_device_ctrl_block_release,
509e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	.sysfs_ops = &device_block_ops,
510079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	.default_attrs = (struct attribute **)device_block_attr,
511e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson};
512e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
5131c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson/* block ctor/dtor  code */
514e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
515e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
516e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * edac_device_create_block
517e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
518079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
519052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				struct edac_device_instance *instance,
5201c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson				struct edac_device_block *block)
521e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
522fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson	int i;
523e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	int err;
524fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson	struct edac_dev_sysfs_block_attribute *sysfs_attrib;
5251c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	struct kobject *main_kobj;
526e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
527b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	debugf4("%s() Instance '%s' inst_p=%p  block '%s'  block_p=%p\n",
528b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson		__func__, instance->name, instance, block->name, block);
529b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	debugf4("%s() block kobj=%p  block kobj->parent=%p\n",
530b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson		__func__, &block->kobj, &block->kobj.parent);
531e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
532e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* init this block's kobject */
533079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	memset(&block->kobj, 0, sizeof(struct kobject));
534e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
5351c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* bump the main kobject's reference count for this controller
53625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 * and this instance is dependent on the main
5371c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
5381c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	main_kobj = kobject_get(&edac_dev->kobj);
5391c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	if (!main_kobj) {
5401c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		err = -ENODEV;
5411c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		goto err_out;
5421c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	}
5431c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
5441c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* Add this block's kobject */
545b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman	err = kobject_init_and_add(&block->kobj, &ktype_block_ctrl,
546b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman				   &instance->kobj,
547b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman				   "%s", block->name);
548e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	if (err) {
5491c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		debugf1("%s() Failed to register instance '%s'\n",
550079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson			__func__, block->name);
5511c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		kobject_put(main_kobj);
5521c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		err = -ENODEV;
5531c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		goto err_out;
554e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	}
555e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
556fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson	/* If there are driver level block attributes, then added them
557fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson	 * to the block kobject
558fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson	 */
559fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson	sysfs_attrib = block->block_attributes;
560b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	if (sysfs_attrib && block->nr_attribs) {
561b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson		for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
562b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson
563b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson			debugf4("%s() creating block attrib='%s' "
564b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson				"attrib->%p to kobj=%p\n",
565b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson				__func__,
566b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson				sysfs_attrib->attr.name,
567b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson				sysfs_attrib, &block->kobj);
568b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson
569b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson			/* Create each block_attribute file */
570fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson			err = sysfs_create_file(&block->kobj,
571b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson				&sysfs_attrib->attr);
572fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson			if (err)
573fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson				goto err_on_attrib;
574fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson		}
575fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson	}
576b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman	kobject_uevent(&block->kobj, KOBJ_ADD);
577fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson
578e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	return 0;
579fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson
5801c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* Error unwind stack */
581fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompsonerr_on_attrib:
582c10997f6575f476ff38442fa18fd4a0d80345f9dGreg Kroah-Hartman	kobject_put(&block->kobj);
583fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson
5841c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonerr_out:
585fd309a9d8e63e9176759d00630b65d772ae06e0cDouglas Thompson	return err;
586e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
587e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
588e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
5891c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * edac_device_delete_block(edac_dev,block);
590e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
591079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic void edac_device_delete_block(struct edac_device_ctl_info *edac_dev,
5921c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson				struct edac_device_block *block)
593e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
5941c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	struct edac_dev_sysfs_block_attribute *sysfs_attrib;
5951c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	int i;
596e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
5971c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* if this block has 'attributes' then we need to iterate over the list
5981c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * and 'remove' the attributes on this block
5991c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
6001c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	sysfs_attrib = block->block_attributes;
6011c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	if (sysfs_attrib && block->nr_attribs) {
602b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson		for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
603b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson
604b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson			/* remove each block_attrib file */
6051c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			sysfs_remove_file(&block->kobj,
6061c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson				(struct attribute *) sysfs_attrib);
6071c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		}
6081c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	}
609e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
6101c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* unregister this block's kobject, SEE:
6111c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 *	edac_device_ctrl_block_release() callback operation
6121c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
613c10997f6575f476ff38442fa18fd4a0d80345f9dGreg Kroah-Hartman	kobject_put(&block->kobj);
614e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
615e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
6161c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson/* instance ctor/dtor code */
617e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
618e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
619e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * edac_device_create_instance
620e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	create just one instance of an edac_device 'instance'
621e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
622079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
623052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				int idx)
624e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
625e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	int i, j;
626e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	int err;
627e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	struct edac_device_instance *instance;
6281c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	struct kobject *main_kobj;
629e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
630e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	instance = &edac_dev->instances[idx];
631e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
632e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* Init the instance's kobject */
633079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	memset(&instance->kobj, 0, sizeof(struct kobject));
634e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
6351c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	instance->ctl = edac_dev;
636e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
6371c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* bump the main kobject's reference count for this controller
63825985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 * and this instance is dependent on the main
6391c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
6401c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	main_kobj = kobject_get(&edac_dev->kobj);
6411c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	if (!main_kobj) {
6421c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		err = -ENODEV;
6431c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		goto err_out;
6441c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	}
645e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
646b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman	/* Formally register this instance's kobject under the edac_device */
647b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman	err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl,
648b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman				   &edac_dev->kobj, "%s", instance->name);
649e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	if (err != 0) {
650e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson		debugf2("%s() Failed to register instance '%s'\n",
651079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson			__func__, instance->name);
6521c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		kobject_put(main_kobj);
6531c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		goto err_out;
654e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	}
655e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
656b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	debugf4("%s() now register '%d' blocks for instance %d\n",
657079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson		__func__, instance->nr_blocks, idx);
658e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
659e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* register all blocks of this instance */
660079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	for (i = 0; i < instance->nr_blocks; i++) {
6611c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		err = edac_device_create_block(edac_dev, instance,
6621c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson						&instance->blocks[i]);
663e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson		if (err) {
6641c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			/* If any fail, remove all previous ones */
66552490c8d07680a7ecc3c1a70a16841455d37e96aDouglas Thompson			for (j = 0; j < i; j++)
6661c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson				edac_device_delete_block(edac_dev,
6671c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson							&instance->blocks[j]);
6681c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			goto err_release_instance_kobj;
669e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson		}
670e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	}
671b2ed215a3338b8b16187be8d136153054118a41eGreg Kroah-Hartman	kobject_uevent(&instance->kobj, KOBJ_ADD);
672e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
673b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	debugf4("%s() Registered instance %d '%s' kobject\n",
674e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson		__func__, idx, instance->name);
675e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
676e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	return 0;
6771c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
6781c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* error unwind stack */
6791c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonerr_release_instance_kobj:
680c10997f6575f476ff38442fa18fd4a0d80345f9dGreg Kroah-Hartman	kobject_put(&instance->kobj);
6811c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
6821c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonerr_out:
6831c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	return err;
684e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
685e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
686e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
687e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * edac_device_remove_instance
688e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	remove an edac_device instance
689e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
690079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompsonstatic void edac_device_delete_instance(struct edac_device_ctl_info *edac_dev,
691079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson					int idx)
692e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
693e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	struct edac_device_instance *instance;
6941c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	int i;
695e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
696e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	instance = &edac_dev->instances[idx];
697e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
698e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* unregister all blocks in this instance */
69952490c8d07680a7ecc3c1a70a16841455d37e96aDouglas Thompson	for (i = 0; i < instance->nr_blocks; i++)
7001c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		edac_device_delete_block(edac_dev, &instance->blocks[i]);
701e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
7021c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* unregister this instance's kobject, SEE:
7031c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 *	edac_device_ctrl_instance_release() for callback operation
7041c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
705c10997f6575f476ff38442fa18fd4a0d80345f9dGreg Kroah-Hartman	kobject_put(&instance->kobj);
706e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
707e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
708e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
709e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * edac_device_create_instances
710e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	create the first level of 'instances' for this device
711e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	(ie  'cache' might have 'cache0', 'cache1', 'cache2', etc
712e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
713e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic int edac_device_create_instances(struct edac_device_ctl_info *edac_dev)
714e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
715e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	int i, j;
716e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	int err;
717e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
718e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	debugf0("%s()\n", __func__);
719e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
720e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* iterate over creation of the instances */
721079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	for (i = 0; i < edac_dev->nr_instances; i++) {
722079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson		err = edac_device_create_instance(edac_dev, i);
723e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson		if (err) {
724e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson			/* unwind previous instances on error */
72552490c8d07680a7ecc3c1a70a16841455d37e96aDouglas Thompson			for (j = 0; j < i; j++)
726079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson				edac_device_delete_instance(edac_dev, j);
727e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson			return err;
728e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson		}
729e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	}
730e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
731e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	return 0;
732e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
733e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
734e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
735e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * edac_device_delete_instances(edac_dev);
736e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	unregister all the kobjects of the instances
737e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
738e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonstatic void edac_device_delete_instances(struct edac_device_ctl_info *edac_dev)
739e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
740e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	int i;
741e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
742e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* iterate over creation of the instances */
74352490c8d07680a7ecc3c1a70a16841455d37e96aDouglas Thompson	for (i = 0; i < edac_dev->nr_instances; i++)
744079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson		edac_device_delete_instance(edac_dev, i);
745e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
746e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
7471c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson/* edac_dev sysfs ctor/dtor  code */
748e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
749e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
7501c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * edac_device_add_main_sysfs_attributes
75142a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson *	add some attributes to this instance's main kobject
75242a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson */
7531c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonstatic int edac_device_add_main_sysfs_attributes(
75442a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson			struct edac_device_ctl_info *edac_dev)
75542a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson{
756052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	struct edac_dev_sysfs_attribute *sysfs_attrib;
7571c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	int err = 0;
758052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson
759052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	sysfs_attrib = edac_dev->sysfs_attributes;
7601c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	if (sysfs_attrib) {
7611c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		/* iterate over the array and create an attribute for each
7621c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		 * entry in the list
7631c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		 */
7641c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		while (sysfs_attrib->attr.name != NULL) {
7651c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			err = sysfs_create_file(&edac_dev->kobj,
766052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson				(struct attribute*) sysfs_attrib);
7671c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			if (err)
7681c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson				goto err_out;
769052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson
7701c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			sysfs_attrib++;
7711c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		}
772052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson	}
77342a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson
7741c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonerr_out:
7751c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	return err;
7761c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson}
7771c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
7781c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson/*
7791c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * edac_device_remove_main_sysfs_attributes
7801c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson *	remove any attributes to this instance's main kobject
7811c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson */
7821c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonstatic void edac_device_remove_main_sysfs_attributes(
7831c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			struct edac_device_ctl_info *edac_dev)
7841c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson{
7851c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	struct edac_dev_sysfs_attribute *sysfs_attrib;
7861c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
7871c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* if there are main attributes, defined, remove them. First,
7881c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * point to the start of the array and iterate over it
7891c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * removing each attribute listed from this device's instance's kobject
7901c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
7911c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	sysfs_attrib = edac_dev->sysfs_attributes;
7921c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	if (sysfs_attrib) {
7931c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		while (sysfs_attrib->attr.name != NULL) {
7941c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			sysfs_remove_file(&edac_dev->kobj,
7951c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson					(struct attribute *) sysfs_attrib);
7961c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			sysfs_attrib++;
7971c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		}
7981c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	}
79942a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson}
80042a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson
80142a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson/*
802e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * edac_device_create_sysfs() Constructor
803e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *
8041c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * accept a created edac_device control structure
8051c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * and 'export' it to sysfs. The 'main' kobj should already have been
8061c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * created. 'instance' and 'block' kobjects should be registered
8071c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * along with any 'block' attributes from the low driver. In addition,
8081c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * the main attributes (if any) are connected to the main kobject of
8091c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * the control structure.
810e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *
811e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * Return:
812e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	0	Success
813e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *	!0	Failure
814e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
815e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonint edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
816e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
817e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	int err;
818079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson	struct kobject *edac_kobj = &edac_dev->kobj;
819e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
820e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx);
821e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
8221c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/*  go create any main attributes callers wants */
8231c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	err = edac_device_add_main_sysfs_attributes(edac_dev);
8241c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	if (err) {
8251c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		debugf0("%s() failed to add sysfs attribs\n", __func__);
8261c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		goto err_out;
82742a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson	}
82842a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson
829e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* create a symlink from the edac device
830e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	 * to the platform 'device' being used for this
831e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	 */
832e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	err = sysfs_create_link(edac_kobj,
833079708b9173595bf74b31b14c36e946359ae6c7eDouglas Thompson				&edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK);
834e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	if (err) {
835e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson		debugf0("%s() sysfs_create_link() returned err= %d\n",
836e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson			__func__, err);
8371c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		goto err_remove_main_attribs;
838e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	}
839e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
8401c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* Create the first level instance directories
8411c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * In turn, the nested blocks beneath the instances will
8421c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 * be registered as well
8431c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	 */
844e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	err = edac_device_create_instances(edac_dev);
8451c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	if (err) {
8461c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		debugf0("%s() edac_device_create_instances() "
8471c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson			"returned err= %d\n", __func__, err);
84842a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson		goto err_remove_link;
8491c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	}
8501c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
8511c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson
852b2a4ac0c2860b27670bce99e8c9c281bf431c272Doug Thompson	debugf4("%s() create-instances done, idx=%d\n",
8531c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson		__func__, edac_dev->dev_idx);
854e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
855e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	return 0;
856e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
857e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	/* Error unwind stack */
85842a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompsonerr_remove_link:
85942a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson	/* remove the sym link */
86042a8e397a80c277afb2aeb22232bc70114035bb1Douglas Thompson	sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
861e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
8621c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonerr_remove_main_attribs:
8631c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	edac_device_remove_main_sysfs_attributes(edac_dev);
864e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
8651c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompsonerr_out:
866e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	return err;
867e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
868e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
869e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson/*
870e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson * edac_device_remove_sysfs() destructor
871e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson *
8721c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson * given an edac_device struct, tear down the kobject resources
873e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson */
874e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompsonvoid edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev)
875e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson{
876e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	debugf0("%s()\n", __func__);
877e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
8781c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* remove any main attributes for this device */
8791c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	edac_device_remove_main_sysfs_attributes(edac_dev);
880e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
8811c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* remove the device sym link */
882e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson	sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
883e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson
8841c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	/* walk the instance/block kobject tree, deconstructing it */
8851c3631ff1f805cb72644fcde02b7c58950f21cd5Douglas Thompson	edac_device_delete_instances(edac_dev);
886e27e3dac651771fe3250f6305dee277bce29fc5dDouglas Thompson}
887