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