/* * * edac_pci_create_sysfs * * Create the controls/attributes for the specified EDAC PCI device */ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) { int err; struct kobject *edac_kobj = &pci->kobj; debugf0("%s() idx=%d\n", __func__, pci->pci_idx); /* create the top main EDAC PCI kobject, IF needed */ err = edac_pci_main_kobj_setup(); if (err) return err; /* Create this instance's kobject under the MAIN kobject */ err = edac_pci_create_instance_kobj(pci, pci->pci_idx); if (err) goto unregister_cleanup; err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK); if (err) { debugf0("%s() sysfs_create_link() returned err= %d\n", __func__, err); goto symlink_fail; } return 0; /* Error unwind stack */ symlink_fail: edac_pci_unregister_sysfs_instance_kobj(pci); unregister_cleanup: edac_pci_main_kobj_teardown(); return err; }
/* * edac_device_create_sysfs() Constructor * * accept a created edac_device control structure * and 'export' it to sysfs. The 'main' kobj should already have been * created. 'instance' and 'block' kobjects should be registered * along with any 'block' attributes from the low driver. In addition, * the main attributes (if any) are connected to the main kobject of * the control structure. * * Return: * 0 Success * !0 Failure */ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) { int err; struct kobject *edac_kobj = &edac_dev->kobj; debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx); /* go create any main attributes callers wants */ err = edac_device_add_main_sysfs_attributes(edac_dev); if (err) { debugf0("%s() failed to add sysfs attribs\n", __func__); goto err_out; } /* create a symlink from the edac device * to the platform 'device' being used for this */ err = sysfs_create_link(edac_kobj, &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK); if (err) { debugf0("%s() sysfs_create_link() returned err= %d\n", __func__, err); goto err_remove_main_attribs; } /* Create the first level instance directories * In turn, the nested blocks beneath the instances will * be registered as well */ err = edac_device_create_instances(edac_dev); if (err) { debugf0("%s() edac_device_create_instances() " "returned err= %d\n", __func__, err); goto err_remove_link; } debugf4("%s() create-instances done, idx=%d\n", __func__, edac_dev->dev_idx); return 0; /* Error unwind stack */ err_remove_link: /* remove the sym link */ sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK); err_remove_main_attribs: edac_device_remove_main_sysfs_attributes(edac_dev); err_out: return err; }
static int how_many_channels(struct pci_dev *pdev) { unsigned char capid0_8b; pci_read_config_byte(pdev, I3200_CAPID0 + 8, &capid0_8b); if (capid0_8b & 0x20) { debugf0("In single channel mode.\n"); return 1; } else { debugf0("In dual channel mode.\n"); return 2; } }
static int how_many_channels(struct pci_dev *pdev) { unsigned char capid0_8b; /* 8th byte of CAPID0 */ pci_read_config_byte(pdev, I3200_CAPID0 + 8, &capid0_8b); if (capid0_8b & 0x20) { /* check DCD: Dual Channel Disable */ debugf0("In single channel mode.\n"); return 1; } else { debugf0("In dual channel mode.\n"); return 2; } }
/* * edac_pci_main_kobj_teardown() * * if no longer linked (needed) remove the top level EDAC PCI * kobject with its controls and attributes */ static void edac_pci_main_kobj_teardown(void) { debugf0("%s()\n", __func__); /* Decrement the count and only if no more controller instances * are connected perform the unregisteration of the top level * main kobj */ if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) { debugf0("%s() called kobject_put on main kobj\n", __func__); kobject_put(edac_pci_top_main_kobj); } }
/* * Do a DRAM ECC write. Assemble staged values in the pvt area and format into * fields needed by the injection registers. */ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci, const char *data, size_t count) { struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; u32 section, word_bits; int ret = 0; ret = strict_strtoul(data, 10, &value); if (ret != -EINVAL) { /* Form value to choose 16-byte section of cacheline */ section = F10_NB_ARRAY_DRAM_ECC | SET_NB_ARRAY_ADDRESS(pvt->injection.section); pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_ARRAY_ADDR, section); word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word, pvt->injection.bit_map); /* Issue 'word' and 'bit' along with the READ request */ pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_ARRAY_DATA, word_bits); debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); return count; } return ret; }
static void edac_sysfs_pci_teardown(void) { debugf0("%s()\n", __func__); init_completion(&edac_pci_kobj_complete); kobject_unregister(&edac_pci_kobj); wait_for_completion(&edac_pci_kobj_complete); }
/* * edac_pci_remove_sysfs * * remove the controls and attributes for this EDAC PCI device */ void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) { debugf0("%s() index=%d\n", __func__, pci->pci_idx); /* Remove the symlink */ sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK); /* remove this PCI instance's sysfs entries */ edac_pci_unregister_sysfs_instance_kobj(pci); /* Call the main unregister function, which will determine * if this 'pci' is the last instance. * If it is, the main kobject will be unregistered as a result */ debugf0("%s() calling edac_pci_main_kobj_teardown()\n", __func__); edac_pci_main_kobj_teardown(); }
/* returns count (>= 0), or negative on error */ static int __devinit r82600_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { debugf0("%s()\n", __func__); /* don't need to call pci_enable_device() */ return r82600_probe1(pdev, ent->driver_data); }
/* * edac_exit() * module exit/termination function */ static void __exit edac_exit(void) { debugf0("%s()\n", __func__); /* tear down the various subsystems */ edac_workqueue_teardown(); edac_sysfs_teardown_mc_kset(); }
int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) { int err; struct kobject *edac_kobj = &edac_dev->kobj; debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx); err = edac_device_add_main_sysfs_attributes(edac_dev); if (err) { debugf0("%s() failed to add sysfs attribs\n", __func__); goto err_out; } err = sysfs_create_link(edac_kobj, &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK); if (err) { debugf0("%s() sysfs_create_link() returned err= %d\n", __func__, err); goto err_remove_main_attribs; } err = edac_device_create_instances(edac_dev); if (err) { debugf0("%s() edac_device_create_instances() " "returned err= %d\n", __func__, err); goto err_remove_link; } debugf4("%s() create-instances done, idx=%d\n", __func__, edac_dev->dev_idx); return 0; err_remove_link: sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK); err_remove_main_attribs: edac_device_remove_main_sysfs_attributes(edac_dev); err_out: return err; }
void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev) { debugf0("%s()\n", __func__); debugf4("%s() name of kobject is: %s\n", __func__, kobject_name(&dev->kobj)); kobject_put(&dev->kobj); edac_put_sysfs_subsys(); }
/* * edac_pci_unregister_sysfs_instance_kobj * * unregister the kobj for the EDAC PCI instance */ static 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_put(&pci->kobj); }
/* * 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__); kfree(kobj); /* last reference to top EDAC PCI kobject has been removed, * NOW release our ref count on the core module */ module_put(THIS_MODULE); }
static void __devexit r82600_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; debugf0("%s()\n", __func__); if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) return; edac_mc_free(mci); }
/* * edac_device_remove_sysfs() destructor * * given an edac_device struct, tear down the kobject resources */ void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev) { debugf0("%s()\n", __func__); /* remove any main attributes for this device */ edac_device_remove_main_sysfs_attributes(edac_dev); /* remove the device sym link */ sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK); /* walk the instance/block kobject tree, deconstructing it */ edac_device_delete_instances(edac_dev); }
void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev) { debugf0("%s()\n", __func__); edac_device_remove_main_sysfs_attributes(edac_dev); sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK); edac_device_delete_instances(edac_dev); }
static int __init i3000_init(void) { int pci_rc; debugf3("MC: %s()\n", __func__); pci_rc = pci_register_driver(&i3000_driver); if (pci_rc < 0) goto fail0; if (mci_pdev == NULL) { i3000_registered = 0; mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_3000_HB, NULL); if (!mci_pdev) { debugf0("i3000 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } pci_rc = i3000_init_one(mci_pdev, i3000_pci_tbl); if (pci_rc < 0) { debugf0("i3000 init fail\n"); pci_rc = -ENODEV; goto fail1; } } return 0; fail1: pci_unregister_driver(&i3000_driver); fail0: if (mci_pdev) pci_dev_put(mci_pdev); return pci_rc; }
/* 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 */ }
/* * MC teardown: * the '..../edac/mc' kobject followed by '..../edac' itself */ static void edac_sysfs_memctrl_teardown(void) { debugf0("MC: " __FILE__ ": %s()\n", __func__); /* Unregister the MC's kobject and wait for reference count to reach * 0. */ init_completion(&edac_memctrl_kobj_complete); kobject_unregister(&edac_memctrl_kobj); wait_for_completion(&edac_memctrl_kobj_complete); /* Unregister the 'edac' object */ sysdev_class_unregister(&edac_class); }
/* Clear any PCI parity errors logged by this device. */ static void edac_pci_dev_parity_clear(struct pci_dev *dev) { u8 header_type; debugf0("%s()\n", __func__); get_pci_parity_status(dev, 0); /* read the device TYPE, looking for bridges */ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) get_pci_parity_status(dev, 1); }
/* returns count (>= 0), or negative on error */ static int __devinit i3000_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; debugf0("MC: %s()\n", __func__); if (pci_enable_device(pdev) < 0) return -EIO; rc = i3000_probe1(pdev, ent->driver_data); if (mci_pdev == NULL) mci_pdev = pci_dev_get(pdev); return rc; }
/* * edac_device_unregister_sysfs_main_kobj: * the '..../edac/<name>' kobject */ void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev) { debugf0("%s()\n", __func__); debugf4("%s() name of kobject is: %s\n", __func__, kobject_name(&dev->kobj)); /* * Unregister the edac device's kobject and * allow for reference count to reach 0 at which point * the callback will be called to: * a) module_put() this module * b) 'kfree' the memory */ kobject_put(&dev->kobj); edac_put_sysfs_class(); }
static int mpc85xx_l2_err_remove(struct of_device *op) { struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; debugf0("%s()\n", __func__); if (edac_op_state == EDAC_OPSTATE_INT) { out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, 0); irq_dispose_mapping(pdata->irq); } out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, orig_l2_err_disable); edac_device_del_device(&op->dev); edac_device_free_ctl_info(edac_dev); return 0; }
static int mpc85xx_mc_err_remove(struct of_device *op) { struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; debugf0("%s()\n", __func__); if (edac_op_state == EDAC_OPSTATE_INT) { out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN, 0); irq_dispose_mapping(pdata->irq); } out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE, orig_ddr_err_disable); out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, orig_ddr_err_sbe); edac_mc_del_mc(&op->dev); edac_mc_free(mci); return 0; }
static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev) { int i, j; int err; debugf0("%s()\n", __func__); for (i = 0; i < edac_dev->nr_instances; i++) { err = edac_device_create_instance(edac_dev, i); if (err) { for (j = 0; j < i; j++) edac_device_delete_instance(edac_dev, j); return err; } } return 0; }
/* * edac_device_create_instances * create the first level of 'instances' for this device * (ie 'cache' might have 'cache0', 'cache1', 'cache2', etc */ static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev) { int i, j; int err; debugf0("%s()\n", __func__); /* iterate over creation of the instances */ for (i = 0; i < edac_dev->nr_instances; i++) { err = edac_device_create_instance(edac_dev, i); if (err) { /* unwind previous instances on error */ for (j = 0; j < i; j++) edac_device_delete_instance(edac_dev, j); return err; } } return 0; }
static int mpc85xx_pci_err_remove(struct of_device *op) { struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); struct mpc85xx_pci_pdata *pdata = pci->pvt_info; debugf0("%s()\n", __func__); out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, orig_pci_err_cap_dr); out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en); edac_pci_del_device(pci->dev); if (edac_op_state == EDAC_OPSTATE_INT) irq_dispose_mapping(pdata->irq); edac_pci_free_ctl_info(pci); return 0; }
/* * accept a hex value and store it into the virtual error register file, field: * nbeal and nbeah. Assume virtual error values have already been set for: NBSL, * NBSH and NBCFG. Then proceed to map the error values to a MC, CSROW and * CHANNEL */ static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data, size_t count) { struct amd64_pvt *pvt = mci->pvt_info; unsigned long long value; int ret = 0; ret = strict_strtoull(data, 16, &value); if (ret != -EINVAL) { debugf0("received NBEA= 0x%llx\n", value); /* place the value into the virtual error packet */ pvt->ctl_error_info.nbeal = (u32) value; value >>= 32; pvt->ctl_error_info.nbeah = (u32) value; /* Process the Mapping request */ /* TODO: Add race prevention */ amd_decode_nb_mce(pvt->mc_node_id, &pvt->ctl_error_info, 1); return count; }
/* * 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; }