static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) { int i; struct i5100_priv *priv = mci->pvt_info; for (i = 0; i < mci->tot_dimms; i++) { struct dimm_info *dimm; const unsigned long npages = i5100_npages(mci, i); const unsigned chan = i5100_csrow_to_chan(mci, i); const unsigned rank = i5100_csrow_to_rank(mci, i); if (!npages) continue; dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, chan, rank, 0); dimm->nr_pages = npages; if (npages) { dimm->grain = 32; dimm->dtype = (priv->mtr[chan][rank].width == 4) ? DEV_X4 : DEV_X8; dimm->mtype = MEM_RDDR2; dimm->edac_mode = EDAC_SECDED; snprintf(dimm->label, sizeof(dimm->label), "DIMM%u", i5100_rank_to_slot(mci, chan, rank)); } debugf2("dimm channel %d, rank %d, size %ld\n", chan, rank, (long)PAGES_TO_MiB(npages)); } }
static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, int idx) { int i, j; int err; struct edac_device_instance *instance; struct kobject *main_kobj; instance = &edac_dev->instances[idx]; memset(&instance->kobj, 0, sizeof(struct kobject)); instance->ctl = edac_dev; main_kobj = kobject_get(&edac_dev->kobj); if (!main_kobj) { err = -ENODEV; goto err_out; } err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl, &edac_dev->kobj, "%s", instance->name); if (err != 0) { debugf2("%s() Failed to register instance '%s'\n", __func__, instance->name); kobject_put(main_kobj); goto err_out; } debugf4("%s() now register '%d' blocks for instance %d\n", __func__, instance->nr_blocks, idx); for (i = 0; i < instance->nr_blocks; i++) { err = edac_device_create_block(edac_dev, instance, &instance->blocks[i]); if (err) { for (j = 0; j < i; j++) edac_device_delete_block(edac_dev, &instance->blocks[j]); goto err_release_instance_kobj; } } kobject_uevent(&instance->kobj, KOBJ_ADD); debugf4("%s() Registered instance %d '%s' kobject\n", __func__, idx, instance->name); return 0; err_release_instance_kobj: kobject_put(&instance->kobj); err_out: 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; }
static int r82600_probe1(struct pci_dev *pdev, int dev_idx) { struct mem_ctl_info *mci; u8 dramcr; u32 eapr; u32 scrub_disabled; u32 sdram_refresh_rate; struct r82600_error_info discard; debugf0("%s()\n", __func__); pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); pci_read_config_dword(pdev, R82600_EAP, &eapr); scrub_disabled = eapr & BIT(31); sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); debugf2("%s(): sdram refresh rate = %#0x\n", __func__, sdram_refresh_rate); debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS, 0); if (mci == NULL) return -ENOMEM; debugf0("%s(): mci = %p\n", __func__, mci); mci->dev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; /* FIXME try to work out if the chip leads have been used for COM2 * instead on this board? [MA6?] MAYBE: */ /* On the R82600, the pins for memory bits 72:65 - i.e. the * * EC bits are shared with the pins for COM2 (!), so if COM2 * * is enabled, we assume COM2 is wired up, and thus no EDAC * * is possible. */ mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; if (ecc_enabled(dramcr)) { if (scrub_disabled) debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " "%#0x\n", __func__, mci, eapr); } else mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = EDAC_MOD_STR; mci->mod_ver = R82600_REVISION; mci->ctl_name = "R82600"; mci->dev_name = pci_name(pdev); mci->edac_check = r82600_check; mci->ctl_page_to_phys = NULL; r82600_init_csrows(mci, pdev, dramcr); r82600_get_error_info(mci, &discard); /* clear counters */ /* Here we assume that we will never see multiple instances of this * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); goto fail; } /* get this far and it's successful */ if (disable_hardware_scrub) { debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n", __func__); pci_write_bits32(pdev, R82600_EAP, BIT(31), BIT(31)); } /* allocating generic PCI control info */ r82600_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); if (!r82600_pci) { printk(KERN_WARNING "%s(): Unable to create PCI control\n", __func__); printk(KERN_WARNING "%s(): PCI error report via EDAC not setup\n", __func__); } debugf3("%s(): success\n", __func__); return 0; fail: edac_mc_free(mci); return -ENODEV; }
/* * edac_device_create_instance * create just one instance of an edac_device 'instance' */ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, int idx) { int i, j; int err; struct edac_device_instance *instance; struct kobject *main_kobj; instance = &edac_dev->instances[idx]; /* Init the instance's kobject */ memset(&instance->kobj, 0, sizeof(struct kobject)); instance->ctl = edac_dev; /* 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; } /* Formally register this instance's kobject under the edac_device */ err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl, &edac_dev->kobj, "%s", instance->name); if (err != 0) { debugf2("%s() Failed to register instance '%s'\n", __func__, instance->name); kobject_put(main_kobj); goto err_out; } debugf4("%s() now register '%d' blocks for instance %d\n", __func__, instance->nr_blocks, idx); /* register all blocks of this instance */ for (i = 0; i < instance->nr_blocks; i++) { err = edac_device_create_block(edac_dev, instance, &instance->blocks[i]); if (err) { /* If any fail, remove all previous ones */ for (j = 0; j < i; j++) edac_device_delete_block(edac_dev, &instance->blocks[j]); goto err_release_instance_kobj; } } kobject_uevent(&instance->kobj, KOBJ_ADD); debugf4("%s() Registered instance %d '%s' kobject\n", __func__, idx, instance->name); return 0; /* error unwind stack */ err_release_instance_kobj: kobject_put(&instance->kobj); err_out: return err; }
/* * PCI Parity polling * */ static void edac_pci_dev_parity_test(struct pci_dev *dev) { u16 status; u8 header_type; /* read the STATUS register on this device */ status = get_pci_parity_status(dev, 0); debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id ); /* check the status reg for errors */ if (status) { if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) edac_printk(KERN_CRIT, EDAC_PCI, "Signaled System Error on %s\n", pci_name(dev)); if (status & (PCI_STATUS_PARITY)) { edac_printk(KERN_CRIT, EDAC_PCI, "Master Data Parity Error on %s\n", pci_name(dev)); atomic_inc(&pci_parity_count); } if (status & (PCI_STATUS_DETECTED_PARITY)) { edac_printk(KERN_CRIT, EDAC_PCI, "Detected Parity Error on %s\n", pci_name(dev)); atomic_inc(&pci_parity_count); } } /* read the device TYPE, looking for bridges */ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id ); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* On bridges, need to examine secondary status register */ status = get_pci_parity_status(dev, 1); debugf2("PCI SEC_STATUS= 0x%04x %s\n", status, dev->dev.bus_id ); /* check the secondary status reg for errors */ if (status) { if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " "Signaled System Error on %s\n", pci_name(dev)); if (status & (PCI_STATUS_PARITY)) { edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " "Master Data Parity Error on " "%s\n", pci_name(dev)); atomic_inc(&pci_parity_count); } if (status & (PCI_STATUS_DETECTED_PARITY)) { edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " "Detected Parity Error on %s\n", pci_name(dev)); atomic_inc(&pci_parity_count); } } } }