/* Initialize the main sysfs entries for edac: * /sys/devices/system/edac * * and children * * Return: 0 SUCCESS * !0 FAILURE */ static int edac_sysfs_memctrl_setup(void) { int err=0; debugf1("%s()\n", __func__); /* create the /sys/devices/system/edac directory */ err = sysdev_class_register(&edac_class); if (!err) { /* Init the MC's kobject */ memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj)); edac_memctrl_kobj.parent = &edac_class.kset.kobj; edac_memctrl_kobj.ktype = &ktype_memctrl; /* generate sysfs "..../edac/mc" */ err = kobject_set_name(&edac_memctrl_kobj,"mc"); if (!err) { /* FIXME: maybe new sysdev_create_subdir() */ err = kobject_register(&edac_memctrl_kobj); if (err) debugf1("Failed to register '.../edac/mc'\n"); else debugf1("Registered '.../edac/mc' kobject\n"); } } else debugf1("%s() error=%d\n", __func__, err); return err; }
/* * edac_device_register_sysfs_main_kobj * * perform the high level setup for the new edac_device instance * * Return: 0 SUCCESS * !0 FAILURE */ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) { struct sysdev_class *edac_class; int err; debugf1("%s()\n", __func__); /* get the /sys/devices/system/edac reference */ edac_class = edac_get_edac_class(); if (edac_class == NULL) { debugf1("%s() no edac_class error\n", __func__); err = -ENODEV; goto err_out; } /* Point to the 'edac_class' this instance 'reports' to */ edac_dev->edac_class = edac_class; /* Init the devices's kobject */ memset(&edac_dev->kobj, 0, sizeof(struct kobject)); /* Record which module 'owns' this control structure * and bump the ref count of the module */ edac_dev->owner = THIS_MODULE; if (!try_module_get(edac_dev->owner)) { err = -ENODEV; goto err_out; } /* register */ err = kobject_init_and_add(&edac_dev->kobj, &ktype_device_ctrl, &edac_class->kset.kobj, "%s", edac_dev->name); if (err) { debugf1("%s()Failed to register '.../edac/%s'\n", __func__, edac_dev->name); goto err_kobj_reg; } kobject_uevent(&edac_dev->kobj, KOBJ_ADD); /* At this point, to 'free' the control struct, * edac_device_unregister_sysfs_main_kobj() must be used */ debugf4("%s() Registered '.../edac/%s' kobject\n", __func__, edac_dev->name); return 0; /* Error exit stack */ err_kobj_reg: module_put(edac_dev->owner); err_out: return err; }
int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) { struct bus_type *edac_subsys; int err; debugf1("%s()\n", __func__); edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { debugf1("%s() no edac_subsys error\n", __func__); err = -ENODEV; goto err_out; } edac_dev->edac_subsys = edac_subsys; memset(&edac_dev->kobj, 0, sizeof(struct kobject)); edac_dev->owner = THIS_MODULE; if (!try_module_get(edac_dev->owner)) { err = -ENODEV; goto err_mod_get; } err = kobject_init_and_add(&edac_dev->kobj, &ktype_device_ctrl, &edac_subsys->dev_root->kobj, "%s", edac_dev->name); if (err) { debugf1("%s()Failed to register '.../edac/%s'\n", __func__, edac_dev->name); goto err_kobj_reg; } kobject_uevent(&edac_dev->kobj, KOBJ_ADD); debugf4("%s() Registered '.../edac/%s' kobject\n", __func__, edac_dev->name); return 0; err_kobj_reg: module_put(edac_dev->owner); err_mod_get: edac_put_sysfs_subsys(); err_out: return err; }
static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, u8 dramcr) { struct csrow_info *csrow; struct dimm_info *dimm; int index; u8 drbar; /* SDRAM Row Boundary Address Register */ u32 row_high_limit, row_high_limit_last; u32 reg_sdram, ecc_on, row_base; ecc_on = ecc_enabled(dramcr); reg_sdram = dramcr & BIT(4); row_high_limit_last = 0; for (index = 0; index < mci->nr_csrows; index++) { csrow = &mci->csrows[index]; dimm = csrow->channels[0].dimm; /* find the DRAM Chip Select Base address and mask */ pci_read_config_byte(pdev, R82600_DRBA + index, &drbar); debugf1("%s() Row=%d DRBA = %#0x\n", __func__, index, drbar); row_high_limit = ((u32) drbar << 24); /* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */ debugf1("%s() Row=%d, Boundary Address=%#0x, Last = %#0x\n", __func__, index, row_high_limit, row_high_limit_last); /* Empty row [p.57] */ if (row_high_limit == row_high_limit_last) continue; row_base = row_high_limit_last; csrow->first_page = row_base >> PAGE_SHIFT; csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; dimm->nr_pages = csrow->last_page - csrow->first_page + 1; /* Error address is top 19 bits - so granularity is * * 14 bits */ dimm->grain = 1 << 14; dimm->mtype = reg_sdram ? MEM_RDDR : MEM_DDR; /* FIXME - check that this is unknowable with this chipset */ dimm->dtype = DEV_UNKNOWN; /* Mode is global on 82600 */ dimm->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE; row_high_limit_last = row_high_limit; } }
static void r82600_check(struct mem_ctl_info *mci) { struct r82600_error_info info; debugf1("MC%d: %s()\n", mci->mc_idx, __func__); r82600_get_error_info(mci, &info); r82600_process_error_info(mci, &info, 1); }
static void edac_device_ctrl_instance_release(struct kobject *kobj) { struct edac_device_instance *instance; debugf1("%s()\n", __func__); instance = to_instance(kobj); kobject_put(&instance->ctl->kobj); }
static void edac_device_ctrl_block_release(struct kobject *kobj) { struct edac_device_block *block; debugf1("%s()\n", __func__); block = to_block(kobj); kobject_put(&block->instance->ctl->kobj); }
/* DEVICE instance kobject release() function */ static void edac_device_ctrl_instance_release(struct kobject *kobj) { struct edac_device_instance *instance; debugf1("%s()\n", __func__); /* map from this kobj to the main control struct * and then dec the main kobj count */ instance = to_instance(kobj); kobject_put(&instance->ctl->kobj); }
/* DEVICE block kobject release() function */ static void edac_device_ctrl_block_release(struct kobject *kobj) { struct edac_device_block *block; debugf1("%s()\n", __func__); /* get the container of the kobj */ block = to_block(kobj); /* map from 'block kobj' to 'block->instance->controller->main_kobj' * now 'release' the block kobject */ kobject_put(&block->instance->ctl->kobj); }
/* * edac_register_sysfs_edac_name() * * register the 'edac' into /sys/devices/system * * return: * 0 success * !0 error */ static int edac_register_sysfs_edac_name(void) { int err; /* create the /sys/devices/system/edac directory */ err = sysdev_class_register(&edac_class); if (err) { debugf1("%s() error=%d\n", __func__, err); return err; } edac_class_valid = 1; return 0; }
/** * edac_sysfs_pci_setup() * */ static int edac_sysfs_pci_setup(void) { int err; debugf1("%s()\n", __func__); memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj)); edac_pci_kobj.parent = &edac_class.kset.kobj; edac_pci_kobj.ktype = &ktype_edac_pci; err = kobject_set_name(&edac_pci_kobj, "pci"); if (!err) { /* Instanstiate the csrow object */ /* FIXME: maybe new sysdev_create_subdir() */ err = kobject_register(&edac_pci_kobj); if (err) debugf1("Failed to register '.../edac/pci'\n"); else debugf1("Registered '.../edac/pci' kobject\n"); } return err; }
/* * 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__); /* 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_init_and_add(&pci->kobj, &ktype_pci_instance, edac_pci_top_main_kobj, "pci%d", idx); if (err != 0) { debugf2("%s() failed to register instance pci%d\n", __func__, idx); kobject_put(edac_pci_top_main_kobj); goto error_out; } kobject_uevent(&pci->kobj, KOBJ_ADD); debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx); return 0; /* Error unwind statck */ error_out: return err; }
/* * edac_device_create_block */ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, struct edac_device_instance *instance, struct edac_device_block *block) { int i; int err; struct edac_dev_sysfs_block_attribute *sysfs_attrib; struct kobject *main_kobj; debugf4("%s() Instance '%s' inst_p=%p block '%s' block_p=%p\n", __func__, instance->name, instance, block->name, block); debugf4("%s() block kobj=%p block kobj->parent=%p\n", __func__, &block->kobj, &block->kobj.parent); /* init this block's kobject */ memset(&block->kobj, 0, sizeof(struct kobject)); /* bump the main kobject's reference count for this controller * and this instance is dependant on the main */ main_kobj = kobject_get(&edac_dev->kobj); if (!main_kobj) { err = -ENODEV; goto err_out; } /* Add this block's kobject */ err = kobject_init_and_add(&block->kobj, &ktype_block_ctrl, &instance->kobj, "%s", block->name); if (err) { debugf1("%s() Failed to register instance '%s'\n", __func__, block->name); kobject_put(main_kobj); err = -ENODEV; goto err_out; } /* If there are driver level block attributes, then added them * to the block kobject */ sysfs_attrib = block->block_attributes; if (sysfs_attrib && block->nr_attribs) { for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) { debugf4("%s() creating block attrib='%s' " "attrib->%p to kobj=%p\n", __func__, sysfs_attrib->attr.name, sysfs_attrib, &block->kobj); /* Create each block_attribute file */ err = sysfs_create_file(&block->kobj, &sysfs_attrib->attr); if (err) goto err_on_attrib; } } kobject_uevent(&block->kobj, KOBJ_ADD); return 0; /* Error unwind stack */ err_on_attrib: kobject_put(&block->kobj); err_out: return err; }
static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, struct edac_device_instance *instance, struct edac_device_block *block) { int i; int err; struct edac_dev_sysfs_block_attribute *sysfs_attrib; struct kobject *main_kobj; debugf4("%s() Instance '%s' inst_p=%p block '%s' block_p=%p\n", __func__, instance->name, instance, block->name, block); debugf4("%s() block kobj=%p block kobj->parent=%p\n", __func__, &block->kobj, &block->kobj.parent); memset(&block->kobj, 0, sizeof(struct kobject)); main_kobj = kobject_get(&edac_dev->kobj); if (!main_kobj) { err = -ENODEV; goto err_out; } err = kobject_init_and_add(&block->kobj, &ktype_block_ctrl, &instance->kobj, "%s", block->name); if (err) { debugf1("%s() Failed to register instance '%s'\n", __func__, block->name); kobject_put(main_kobj); err = -ENODEV; goto err_out; } sysfs_attrib = block->block_attributes; if (sysfs_attrib && block->nr_attribs) { for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) { debugf4("%s() creating block attrib='%s' " "attrib->%p to kobj=%p\n", __func__, sysfs_attrib->attr.name, sysfs_attrib, &block->kobj); err = sysfs_create_file(&block->kobj, &sysfs_attrib->attr); if (err) goto err_on_attrib; } } kobject_uevent(&block->kobj, KOBJ_ADD); return 0; err_on_attrib: kobject_put(&block->kobj); err_out: return err; }
/* No memory to release */ static void edac_pci_release(struct kobject *kobj) { debugf1("%s()\n", __func__); complete(&edac_pci_kobj_complete); }
/** * edac_pci_main_kobj_setup() * * setup the sysfs for EDAC PCI attributes * assumes edac_class has already been initialized */ static 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; } /* 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; } edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); if (!edac_pci_top_main_kobj) { debugf1("Failed to allocate\n"); err = -ENOMEM; goto kzalloc_fail; } /* Instanstiate the pci object */ err = kobject_init_and_add(edac_pci_top_main_kobj, &ktype_edac_pci_main_kobj, &edac_class->kset.kobj, "pci"); if (err) { debugf1("Failed to register '.../edac/pci'\n"); goto kobject_init_and_add_fail; } /* At this point, to 'release' the top level kobject * for EDAC PCI, then edac_pci_main_kobj_teardown() * must be used, for resources to be cleaned up properly */ kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD); debugf1("Registered '.../edac/pci' kobject\n"); return 0; /* Error unwind statck */ kobject_init_and_add_fail: kfree(edac_pci_top_main_kobj); kzalloc_fail: module_put(THIS_MODULE); decrement_count_fail: /* if are on this error exit, nothing to tear down */ atomic_dec(&edac_pci_sysfs_refcount); return err; }
/* Main MC kobject release() function */ static void edac_memctrl_master_release(struct kobject *kobj) { debugf1("%s()\n", __func__); complete(&edac_memctrl_kobj_complete); }