Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09854dde authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull EDAC updates from Borislav Petkov:
 - mpc85xx PCIe error interrupt support
 - misc small enhancements/fixes all over the place.

* tag 'edac_for_3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
  EDAC: Don't try to cancel workqueue when it's never setup
  e752x_edac: Fix pci_dev usage count
  sb_edac: Mark get_mci_for_node_id as static
  EDAC: Mark edac_create_debug_nodes as static
  amd64_edac: Remove "amd64" prefix from static functions
  amd64_edac: Simplify code around decode_bus_error
  amd64_edac: Mark amd64_decode_bus_error as static
  EDAC: Remove DEFINE_PCI_DEVICE_TABLE macro
  amd64_edac: Fix condition to verify max channels allowed for F15 M30h
  edac/85xx: Add PCIe error interrupt edac support
parents a1a3b3ef 881f0fce
Loading
Loading
Loading
Loading
+62 −73
Original line number Diff line number Diff line
#include "amd64_edac.h"
#include <asm/amd_nb.h>

static struct edac_pci_ctl_info *amd64_ctl_pci;
static struct edac_pci_ctl_info *pci_ctl;

static int report_gart_errors;
module_param(report_gart_errors, int, 0644);
@@ -162,7 +162,7 @@ static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
 * scan the scrub rate mapping table for a close or matching bandwidth value to
 * issue. If requested is too big, then use last maximum value found.
 */
static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
static int __set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
{
	u32 scrubval;
	int i;
@@ -198,7 +198,7 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
	return 0;
}

static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
static int set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
{
	struct amd64_pvt *pvt = mci->pvt_info;
	u32 min_scrubrate = 0x5;
@@ -210,10 +210,10 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
	if (pvt->fam == 0x15 && pvt->model < 0x10)
		f15h_select_dct(pvt, 0);

	return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate);
	return __set_scrub_rate(pvt->F3, bw, min_scrubrate);
}

static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
static int get_scrub_rate(struct mem_ctl_info *mci)
{
	struct amd64_pvt *pvt = mci->pvt_info;
	u32 scrubval = 0;
@@ -240,8 +240,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
 * returns true if the SysAddr given by sys_addr matches the
 * DRAM base/limit associated with node_id
 */
static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr,
				   u8 nid)
static bool base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, u8 nid)
{
	u64 addr;

@@ -285,7 +284,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,

	if (intlv_en == 0) {
		for (node_id = 0; node_id < DRAM_RANGES; node_id++) {
			if (amd64_base_limit_match(pvt, sys_addr, node_id))
			if (base_limit_match(pvt, sys_addr, node_id))
				goto found;
		}
		goto err_no_match;
@@ -309,7 +308,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
	}

	/* sanity test for sys_addr */
	if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) {
	if (unlikely(!base_limit_match(pvt, sys_addr, node_id))) {
		amd64_warn("%s: sys_addr 0x%llx falls outside base/limit address"
			   "range for node %d with node interleaving enabled.\n",
			   __func__, sys_addr, node_id);
@@ -660,7 +659,7 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16);
 * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs
 * are ECC capable.
 */
static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt)
static unsigned long determine_edac_cap(struct amd64_pvt *pvt)
{
	u8 bit;
	unsigned long edac_cap = EDAC_FLAG_NONE;
@@ -675,9 +674,9 @@ static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt)
	return edac_cap;
}

static void amd64_debug_display_dimm_sizes(struct amd64_pvt *, u8);
static void debug_display_dimm_sizes(struct amd64_pvt *, u8);

static void amd64_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
{
	edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr);

@@ -711,7 +710,7 @@ static void dump_misc_regs(struct amd64_pvt *pvt)
		 (pvt->nbcap & NBCAP_SECDED) ? "yes" : "no",
		 (pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no");

	amd64_dump_dramcfg_low(pvt, pvt->dclr0, 0);
	debug_dump_dramcfg_low(pvt, pvt->dclr0, 0);

	edac_dbg(1, "F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare);

@@ -722,19 +721,19 @@ static void dump_misc_regs(struct amd64_pvt *pvt)

	edac_dbg(1, "  DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no");

	amd64_debug_display_dimm_sizes(pvt, 0);
	debug_display_dimm_sizes(pvt, 0);

	/* everything below this point is Fam10h and above */
	if (pvt->fam == 0xf)
		return;

	amd64_debug_display_dimm_sizes(pvt, 1);
	debug_display_dimm_sizes(pvt, 1);

	amd64_info("using %s syndromes.\n", ((pvt->ecc_sym_sz == 8) ? "x8" : "x4"));

	/* Only if NOT ganged does dclr1 have valid info */
	if (!dct_ganging_enabled(pvt))
		amd64_dump_dramcfg_low(pvt, pvt->dclr1, 1);
		debug_dump_dramcfg_low(pvt, pvt->dclr1, 1);
}

/*
@@ -800,7 +799,7 @@ static void read_dct_base_mask(struct amd64_pvt *pvt)
	}
}

static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt, int cs)
static enum mem_type determine_memory_type(struct amd64_pvt *pvt, int cs)
{
	enum mem_type type;

@@ -1578,7 +1577,7 @@ static int f15_m30h_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
					     num_dcts_intlv, dct_sel);

	/* Verify we stay within the MAX number of channels allowed */
	if (channel > 4 || channel < 0)
	if (channel > 3)
		return -EINVAL;

	leg_mmio_hole = (u8) (dct_cont_base_reg >> 1 & BIT(0));
@@ -1702,7 +1701,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
 * debug routine to display the memory sizes of all logical DIMMs and its
 * CSROWs
 */
static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
{
	int dimm, size0, size1;
	u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
@@ -1744,7 +1743,7 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
	}
}

static struct amd64_family_type amd64_family_types[] = {
static struct amd64_family_type family_types[] = {
	[K8_CPUS] = {
		.ctl_name = "K8",
		.f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
@@ -2005,9 +2004,9 @@ static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err,
			     string, "");
}

static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
					    struct mce *m)
static inline void decode_bus_error(int node_id, struct mce *m)
{
	struct mem_ctl_info *mci = mcis[node_id];
	struct amd64_pvt *pvt = mci->pvt_info;
	u8 ecc_type = (m->status >> 45) & 0x3;
	u8 xec = XEC(m->status, 0x1f);
@@ -2035,11 +2034,6 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
	__log_bus_error(mci, &err, ecc_type);
}

void amd64_decode_bus_error(int node_id, struct mce *m)
{
	__amd64_decode_bus_error(mcis[node_id], m);
}

/*
 * Use pvt->F2 which contains the F2 CPU PCI device to get the related
 * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error.
@@ -2196,7 +2190,7 @@ static void read_mc_regs(struct amd64_pvt *pvt)
 *	encompasses
 *
 */
static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
{
	u32 cs_mode, nr_pages;
	u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
@@ -2263,19 +2257,19 @@ static int init_csrows(struct mem_ctl_info *mci)
			    pvt->mc_node_id, i);

		if (row_dct0) {
			nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
			nr_pages = get_csrow_nr_pages(pvt, 0, i);
			csrow->channels[0]->dimm->nr_pages = nr_pages;
		}

		/* K8 has only one DCT */
		if (pvt->fam != 0xf && row_dct1) {
			int row_dct1_pages = amd64_csrow_nr_pages(pvt, 1, i);
			int row_dct1_pages = get_csrow_nr_pages(pvt, 1, i);

			csrow->channels[1]->dimm->nr_pages = row_dct1_pages;
			nr_pages += row_dct1_pages;
		}

		mtype = amd64_determine_memory_type(pvt, i);
		mtype = determine_memory_type(pvt, i);

		edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);

@@ -2309,7 +2303,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, u16 nid)
}

/* check MCG_CTL on all the cpus on this node */
static bool amd64_nb_mce_bank_enabled_on_node(u16 nid)
static bool nb_mce_bank_enabled_on_node(u16 nid)
{
	cpumask_var_t mask;
	int cpu, nbe;
@@ -2482,7 +2476,7 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid)
	ecc_en = !!(value & NBCFG_ECC_ENABLE);
	amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled"));

	nb_mce_en = amd64_nb_mce_bank_enabled_on_node(nid);
	nb_mce_en = nb_mce_bank_enabled_on_node(nid);
	if (!nb_mce_en)
		amd64_notice("NB MCE bank disabled, set MSR "
			     "0x%08x[4] on node %d to enable.\n",
@@ -2537,7 +2531,7 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
	if (pvt->nbcap & NBCAP_CHIPKILL)
		mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;

	mci->edac_cap		= amd64_determine_edac_cap(pvt);
	mci->edac_cap		= determine_edac_cap(pvt);
	mci->mod_name		= EDAC_MOD_STR;
	mci->mod_ver		= EDAC_AMD64_VERSION;
	mci->ctl_name		= fam->ctl_name;
@@ -2545,14 +2539,14 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
	mci->ctl_page_to_phys	= NULL;

	/* memory scrubber interface */
	mci->set_sdram_scrub_rate = amd64_set_scrub_rate;
	mci->get_sdram_scrub_rate = amd64_get_scrub_rate;
	mci->set_sdram_scrub_rate = set_scrub_rate;
	mci->get_sdram_scrub_rate = get_scrub_rate;
}

/*
 * returns a pointer to the family descriptor on success, NULL otherwise.
 */
static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)
static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
{
	struct amd64_family_type *fam_type = NULL;

@@ -2563,29 +2557,29 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)

	switch (pvt->fam) {
	case 0xf:
		fam_type		= &amd64_family_types[K8_CPUS];
		pvt->ops		= &amd64_family_types[K8_CPUS].ops;
		fam_type	= &family_types[K8_CPUS];
		pvt->ops	= &family_types[K8_CPUS].ops;
		break;

	case 0x10:
		fam_type		= &amd64_family_types[F10_CPUS];
		pvt->ops		= &amd64_family_types[F10_CPUS].ops;
		fam_type	= &family_types[F10_CPUS];
		pvt->ops	= &family_types[F10_CPUS].ops;
		break;

	case 0x15:
		if (pvt->model == 0x30) {
			fam_type	= &amd64_family_types[F15_M30H_CPUS];
			pvt->ops	= &amd64_family_types[F15_M30H_CPUS].ops;
			fam_type = &family_types[F15_M30H_CPUS];
			pvt->ops = &family_types[F15_M30H_CPUS].ops;
			break;
		}

		fam_type		= &amd64_family_types[F15_CPUS];
		pvt->ops		= &amd64_family_types[F15_CPUS].ops;
		fam_type	= &family_types[F15_CPUS];
		pvt->ops	= &family_types[F15_CPUS].ops;
		break;

	case 0x16:
		fam_type		= &amd64_family_types[F16_CPUS];
		pvt->ops		= &amd64_family_types[F16_CPUS].ops;
		fam_type	= &family_types[F16_CPUS];
		pvt->ops	= &family_types[F16_CPUS].ops;
		break;

	default:
@@ -2601,7 +2595,7 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)
	return fam_type;
}

static int amd64_init_one_instance(struct pci_dev *F2)
static int init_one_instance(struct pci_dev *F2)
{
	struct amd64_pvt *pvt = NULL;
	struct amd64_family_type *fam_type = NULL;
@@ -2619,7 +2613,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)
	pvt->F2 = F2;

	ret = -EINVAL;
	fam_type = amd64_per_family_init(pvt);
	fam_type = per_family_init(pvt);
	if (!fam_type)
		goto err_free;

@@ -2680,7 +2674,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)
	if (report_gart_errors)
		amd_report_gart_errors(true);

	amd_register_ecc_decoder(amd64_decode_bus_error);
	amd_register_ecc_decoder(decode_bus_error);

	mcis[nid] = mci;

@@ -2703,7 +2697,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)
	return ret;
}

static int amd64_probe_one_instance(struct pci_dev *pdev,
static int probe_one_instance(struct pci_dev *pdev,
			      const struct pci_device_id *mc_type)
{
	u16 nid = amd_get_node_id(pdev);
@@ -2736,7 +2730,7 @@ static int amd64_probe_one_instance(struct pci_dev *pdev,
			goto err_enable;
	}

	ret = amd64_init_one_instance(pdev);
	ret = init_one_instance(pdev);
	if (ret < 0) {
		amd64_err("Error probing instance: %d\n", nid);
		restore_ecc_error_reporting(s, nid, F3);
@@ -2752,7 +2746,7 @@ static int amd64_probe_one_instance(struct pci_dev *pdev,
	return ret;
}

static void amd64_remove_one_instance(struct pci_dev *pdev)
static void remove_one_instance(struct pci_dev *pdev)
{
	struct mem_ctl_info *mci;
	struct amd64_pvt *pvt;
@@ -2777,7 +2771,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev)

	/* unregister from EDAC MCE */
	amd_report_gart_errors(false);
	amd_unregister_ecc_decoder(amd64_decode_bus_error);
	amd_unregister_ecc_decoder(decode_bus_error);

	kfree(ecc_stngs[nid]);
	ecc_stngs[nid] = NULL;
@@ -2795,7 +2789,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev)
 * PCI core identifies what devices are on a system during boot, and then
 * inquiry this table to see if this driver is for a given device found.
 */
static DEFINE_PCI_DEVICE_TABLE(amd64_pci_table) = {
static const struct pci_device_id amd64_pci_table[] = {
	{
		.vendor		= PCI_VENDOR_ID_AMD,
		.device		= PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
@@ -2843,8 +2837,8 @@ MODULE_DEVICE_TABLE(pci, amd64_pci_table);

static struct pci_driver amd64_pci_driver = {
	.name		= EDAC_MOD_STR,
	.probe		= amd64_probe_one_instance,
	.remove		= amd64_remove_one_instance,
	.probe		= probe_one_instance,
	.remove		= remove_one_instance,
	.id_table	= amd64_pci_table,
};

@@ -2853,23 +2847,18 @@ static void setup_pci_device(void)
	struct mem_ctl_info *mci;
	struct amd64_pvt *pvt;

	if (amd64_ctl_pci)
	if (pci_ctl)
		return;

	mci = mcis[0];
	if (mci) {
	if (!mci)
		return;

	pvt = mci->pvt_info;
		amd64_ctl_pci =
			edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);

		if (!amd64_ctl_pci) {
			pr_warning("%s(): Unable to create PCI control\n",
				   __func__);

			pr_warning("%s(): PCI error report via EDAC not set\n",
				   __func__);
			}
	pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
	if (!pci_ctl) {
		pr_warn("%s(): Unable to create PCI control\n", __func__);
		pr_warn("%s(): PCI error report via EDAC not set\n", __func__);
	}
}

@@ -2925,8 +2914,8 @@ static int __init amd64_edac_init(void)

static void __exit amd64_edac_exit(void)
{
	if (amd64_ctl_pci)
		edac_pci_release_generic_ctl(amd64_ctl_pci);
	if (pci_ctl)
		edac_pci_release_generic_ctl(pci_ctl);

	pci_unregister_driver(&amd64_pci_driver);

+1 −1
Original line number Diff line number Diff line
@@ -333,7 +333,7 @@ static void amd76x_remove_one(struct pci_dev *pdev)
	edac_mc_free(mci);
}

static DEFINE_PCI_DEVICE_TABLE(amd76x_pci_tbl) = {
static const struct pci_device_id amd76x_pci_tbl[] = {
	{
	 PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
	 AMD762},
+4 −2
Original line number Diff line number Diff line
@@ -1182,9 +1182,11 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx,
	pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
				pvt->dev_info->err_dev, pvt->bridge_ck);

	if (pvt->bridge_ck == NULL)
	if (pvt->bridge_ck == NULL) {
		pvt->bridge_ck = pci_scan_single_device(pdev->bus,
							PCI_DEVFN(0, 1));
		pci_dev_get(pvt->bridge_ck);
	}

	if (pvt->bridge_ck == NULL) {
		e752x_printk(KERN_ERR, "error reporting device not found:"
@@ -1421,7 +1423,7 @@ static void e752x_remove_one(struct pci_dev *pdev)
	edac_mc_free(mci);
}

static DEFINE_PCI_DEVICE_TABLE(e752x_pci_tbl) = {
static const struct pci_device_id e752x_pci_tbl[] = {
	{
	 PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
	 E7520},
+1 −1
Original line number Diff line number Diff line
@@ -555,7 +555,7 @@ static void e7xxx_remove_one(struct pci_dev *pdev)
	edac_mc_free(mci);
}

static DEFINE_PCI_DEVICE_TABLE(e7xxx_pci_tbl) = {
static const struct pci_device_id e7xxx_pci_tbl[] = {
	{
	 PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
	 E7205},
+3 −0
Original line number Diff line number Diff line
@@ -437,6 +437,9 @@ void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
{
	int status;

	if (!edac_dev->edac_check)
		return;

	status = cancel_delayed_work(&edac_dev->work);
	if (status == 0) {
		/* workq instance might be running, wait for it */
Loading