edac_pci_sysfs.c
来自「linux 内核源代码」· C语言 代码 · 共 764 行 · 第 1/2 页
C
764 行
/* * (C) 2005, 2006 Linux Networx (http://lnxi.com) * This file may be distributed under the terms of the * GNU General Public License. * * Written Doug Thompson <norsk5@xmission.com> * */#include <linux/module.h>#include <linux/sysdev.h>#include <linux/ctype.h>#include "edac_core.h"#include "edac_module.h"/* Turn off this whole feature if PCI is not configured */#ifdef CONFIG_PCI#define EDAC_PCI_SYMLINK "device"/* data variables exported via sysfs */static int check_pci_errors; /* default NO check PCI parity */static int edac_pci_panic_on_pe; /* default NO panic on PCI Parity */static int edac_pci_log_pe = 1; /* log PCI parity errors */static int edac_pci_log_npe = 1; /* log PCI non-parity error errors */static int edac_pci_poll_msec = 1000; /* one second workq period */static atomic_t pci_parity_count = ATOMIC_INIT(0);static atomic_t pci_nonparity_count = ATOMIC_INIT(0);static struct kobject edac_pci_top_main_kobj;static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0);/* getter functions for the data variables */int edac_pci_get_check_errors(void){ return check_pci_errors;}int edac_pci_get_log_pe(void){ return edac_pci_log_pe;}int edac_pci_get_log_npe(void){ return edac_pci_log_npe;}int edac_pci_get_panic_on_pe(void){ return edac_pci_panic_on_pe;}int edac_pci_get_poll_msec(void){ return edac_pci_poll_msec;}/**************************** EDAC PCI sysfs instance *******************/static ssize_t instance_pe_count_show(struct edac_pci_ctl_info *pci, char *data){ return sprintf(data, "%u\n", atomic_read(&pci->counters.pe_count));}static ssize_t instance_npe_count_show(struct edac_pci_ctl_info *pci, char *data){ return sprintf(data, "%u\n", atomic_read(&pci->counters.npe_count));}#define to_instance(k) container_of(k, struct edac_pci_ctl_info, kobj)#define to_instance_attr(a) container_of(a, struct instance_attribute, attr)/* DEVICE instance kobject release() function */static void edac_pci_instance_release(struct kobject *kobj){ struct edac_pci_ctl_info *pci; debugf0("%s()\n", __func__); /* Form pointer to containing struct, the pci control struct */ pci = to_instance(kobj); /* decrement reference count on top main kobj */ kobject_put(&edac_pci_top_main_kobj); kfree(pci); /* Free the control struct */}/* instance specific attribute structure */struct instance_attribute { struct attribute attr; ssize_t(*show) (struct edac_pci_ctl_info *, char *); ssize_t(*store) (struct edac_pci_ctl_info *, const char *, size_t);};/* Function to 'show' fields from the edac_pci 'instance' structure */static ssize_t edac_pci_instance_show(struct kobject *kobj, struct attribute *attr, char *buffer){ struct edac_pci_ctl_info *pci = to_instance(kobj); struct instance_attribute *instance_attr = to_instance_attr(attr); if (instance_attr->show) return instance_attr->show(pci, buffer); return -EIO;}/* Function to 'store' fields into the edac_pci 'instance' structure */static ssize_t edac_pci_instance_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count){ struct edac_pci_ctl_info *pci = to_instance(kobj); struct instance_attribute *instance_attr = to_instance_attr(attr); if (instance_attr->store) return instance_attr->store(pci, buffer, count); return -EIO;}/* fs_ops table */static struct sysfs_ops pci_instance_ops = { .show = edac_pci_instance_show, .store = edac_pci_instance_store};#define INSTANCE_ATTR(_name, _mode, _show, _store) \static struct instance_attribute attr_instance_##_name = { \ .attr = {.name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .store = _store, \};INSTANCE_ATTR(pe_count, S_IRUGO, instance_pe_count_show, NULL);INSTANCE_ATTR(npe_count, S_IRUGO, instance_npe_count_show, NULL);/* pci instance attributes */static struct instance_attribute *pci_instance_attr[] = { &attr_instance_pe_count, &attr_instance_npe_count, NULL};/* the ktype for a pci instance */static struct kobj_type ktype_pci_instance = { .release = edac_pci_instance_release, .sysfs_ops = &pci_instance_ops, .default_attrs = (struct attribute **)pci_instance_attr,};/* * edac_pci_create_instance_kobj * * construct one EDAC PCI instance's kobject for use */static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx){ struct kobject *main_kobj; int err; debugf0("%s()\n", __func__); /* Set the parent and the instance's ktype */ pci->kobj.parent = &edac_pci_top_main_kobj; pci->kobj.ktype = &ktype_pci_instance; err = kobject_set_name(&pci->kobj, "pci%d", idx); if (err) return err; /* First bump the ref count on the top main kobj, which will * track the number of PCI instances we have, and thus nest * properly on keeping the module loaded */ main_kobj = kobject_get(&edac_pci_top_main_kobj); if (!main_kobj) { err = -ENODEV; goto error_out; } /* And now register this new kobject under the main kobj */ err = kobject_register(&pci->kobj); if (err != 0) { debugf2("%s() failed to register instance pci%d\n", __func__, idx); kobject_put(&edac_pci_top_main_kobj); goto error_out; } debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx); return 0; /* Error unwind statck */error_out: return err;}/* * edac_pci_unregister_sysfs_instance_kobj * * unregister the kobj for the EDAC PCI instance */void edac_pci_unregister_sysfs_instance_kobj(struct edac_pci_ctl_info *pci){ debugf0("%s()\n", __func__); /* Unregister the instance kobject and allow its release * function release the main reference count and then * kfree the memory */ kobject_unregister(&pci->kobj);}/***************************** EDAC PCI sysfs root **********************/#define to_edacpci(k) container_of(k, struct edac_pci_ctl_info, kobj)#define to_edacpci_attr(a) container_of(a, struct edac_pci_attr, attr)/* simple show/store functions for attributes */static ssize_t edac_pci_int_show(void *ptr, char *buffer){ int *value = ptr; return sprintf(buffer, "%d\n", *value);}static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count){ int *value = ptr; if (isdigit(*buffer)) *value = simple_strtoul(buffer, NULL, 0); return count;}struct edac_pci_dev_attribute { struct attribute attr; void *value; ssize_t(*show) (void *, char *); ssize_t(*store) (void *, const char *, size_t);};/* Set of show/store abstract level functions for PCI Parity object */static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer){ struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev = (struct edac_pci_dev_attribute *)attr; if (edac_pci_dev->show) return edac_pci_dev->show(edac_pci_dev->value, buffer); return -EIO;}static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count){ struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev = (struct edac_pci_dev_attribute *)attr; if (edac_pci_dev->show) return edac_pci_dev->store(edac_pci_dev->value, buffer, count); return -EIO;}static struct sysfs_ops edac_pci_sysfs_ops = { .show = edac_pci_dev_show, .store = edac_pci_dev_store};#define EDAC_PCI_ATTR(_name,_mode,_show,_store) \static struct edac_pci_dev_attribute edac_pci_attr_##_name = { \ .attr = {.name = __stringify(_name), .mode = _mode }, \ .value = &_name, \ .show = _show, \ .store = _store, \};#define EDAC_PCI_STRING_ATTR(_name,_data,_mode,_show,_store) \static struct edac_pci_dev_attribute edac_pci_attr_##_name = { \ .attr = {.name = __stringify(_name), .mode = _mode }, \ .value = _data, \ .show = _show, \ .store = _store, \};/* PCI Parity control files */EDAC_PCI_ATTR(check_pci_errors, S_IRUGO | S_IWUSR, edac_pci_int_show, edac_pci_int_store);EDAC_PCI_ATTR(edac_pci_log_pe, S_IRUGO | S_IWUSR, edac_pci_int_show, edac_pci_int_store);EDAC_PCI_ATTR(edac_pci_log_npe, S_IRUGO | S_IWUSR, edac_pci_int_show, edac_pci_int_store);EDAC_PCI_ATTR(edac_pci_panic_on_pe, S_IRUGO | S_IWUSR, edac_pci_int_show, edac_pci_int_store);EDAC_PCI_ATTR(pci_parity_count, S_IRUGO, edac_pci_int_show, NULL);EDAC_PCI_ATTR(pci_nonparity_count, S_IRUGO, edac_pci_int_show, NULL);/* Base Attributes of the memory ECC object */static struct edac_pci_dev_attribute *edac_pci_attr[] = { &edac_pci_attr_check_pci_errors, &edac_pci_attr_edac_pci_log_pe, &edac_pci_attr_edac_pci_log_npe, &edac_pci_attr_edac_pci_panic_on_pe, &edac_pci_attr_pci_parity_count, &edac_pci_attr_pci_nonparity_count, NULL,};/* * edac_pci_release_main_kobj * * This release function is called when the reference count to the * passed kobj goes to zero. * * This kobj is the 'main' kobject that EDAC PCI instances * link to, and thus provide for proper nesting counts */static void edac_pci_release_main_kobj(struct kobject *kobj){ debugf0("%s() here to module_put(THIS_MODULE)\n", __func__); /* last reference to top EDAC PCI kobject has been removed, * NOW release our ref count on the core module */ module_put(THIS_MODULE);}/* ktype struct for the EDAC PCI main kobj */static struct kobj_type ktype_edac_pci_main_kobj = { .release = edac_pci_release_main_kobj, .sysfs_ops = &edac_pci_sysfs_ops, .default_attrs = (struct attribute **)edac_pci_attr,};/** * edac_pci_main_kobj_setup() * * setup the sysfs for EDAC PCI attributes * assumes edac_class has already been initialized */int edac_pci_main_kobj_setup(void){ int err; struct sysdev_class *edac_class; debugf0("%s()\n", __func__); /* check and count if we have already created the main kobject */ if (atomic_inc_return(&edac_pci_sysfs_refcount) != 1) return 0; /* First time, so create the main kobject and its * controls and atributes */ edac_class = edac_get_edac_class(); if (edac_class == NULL) { debugf1("%s() no edac_class\n", __func__); err = -ENODEV; goto decrement_count_fail; } /* Need the kobject hook ups, and name setting */ edac_pci_top_main_kobj.ktype = &ktype_edac_pci_main_kobj; edac_pci_top_main_kobj.parent = &edac_class->kset.kobj; err = kobject_set_name(&edac_pci_top_main_kobj, "pci"); if (err) goto decrement_count_fail; /* Bump the reference count on this module to ensure the * modules isn't unloaded until we deconstruct the top * level main kobj for EDAC PCI */ if (!try_module_get(THIS_MODULE)) { debugf1("%s() try_module_get() failed\n", __func__); err = -ENODEV; goto decrement_count_fail;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?