Subject: AMD64 EDAC fixlets for .33

Hi,

here are a bunch of fixes to several edac buglets and annoyances I've
been meaning to fix but never got around to it, alongside two fixes of
reported problems. They are pretty small and straightforward and I'll
push them to Linus later if there are no objections. Series tested on
your garden variety of K8 and F10h Opterons found around the office.

Borislav Petkov (6):
amd64_edac: fix K8 chip select reporting
amd64_edac: fix driver instance freeing
amd64_edac: make driver loading more robust
amd64_edac: fix forcing module load/unload
amd64_edac: restrict PCI config space access
edac, pci: remove pesky debug printk


drivers/edac/amd64_edac.c | 45 +++++++++++++++++++++++++---------------
drivers/edac/edac_pci_sysfs.c | 2 -
2 files changed, 28 insertions(+), 19 deletions(-)

--
Regards/Gruss,
Boris.


Subject: [PATCH 1/6] amd64_edac: fix K8 chip select reporting

Fix the case when amd64_debug_display_dimm_sizes() reports only half the
amount of DRAM on it because it doesn't account for when the single DCT
operates in 128-bit mode and merges chip selects from different DIMMs.

Reported-by: Johannes Hirte <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
---
drivers/edac/amd64_edac.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index df5b684..784cc5a 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -1700,11 +1700,14 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
*/
static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt)
{
- int dimm, size0, size1;
+ int dimm, size0, size1, factor = 0;
u32 dbam;
u32 *dcsb;

if (boot_cpu_data.x86 == 0xf) {
+ if (pvt->dclr0 & F10_WIDTH_128)
+ factor = 1;
+
/* K8 families < revF not supported yet */
if (pvt->ext_model < K8_REV_F)
return;
@@ -1732,7 +1735,8 @@ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt)
size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam));

edac_printk(KERN_DEBUG, EDAC_MC, " %d: %5dMB %d: %5dMB\n",
- dimm * 2, size0, dimm * 2 + 1, size1);
+ dimm * 2, size0 << factor,
+ dimm * 2 + 1, size1 << factor);
}
}

--
1.6.5.4

Subject: [PATCH 2/6] amd64_edac: fix driver instance freeing

Fix use-after-free errors by pushing all memory-freeing calls to the end
of amd64_remove_one_instance().

Reported-by: Darren Jenkins <[email protected]>
LKML-Reference: <1261370306.11354.52.camel@ICE-BOX>
Signed-off-by: Borislav Petkov <[email protected]>
---
drivers/edac/amd64_edac.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 784cc5a..fb0d36b 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2929,16 +2929,15 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev)

amd64_free_mc_sibling_devices(pvt);

- kfree(pvt);
- mci->pvt_info = NULL;
-
- mci_lookup[pvt->mc_node_id] = NULL;
-
/* unregister from EDAC MCE */
amd_report_gart_errors(false);
amd_unregister_ecc_decoder(amd64_decode_bus_error);

/* Free the EDAC CORE resources */
+ mci->pvt_info = NULL;
+ mci_lookup[pvt->mc_node_id] = NULL;
+
+ kfree(pvt);
edac_mc_free(mci);
}

--
1.6.5.4

Subject: [PATCH 3/6] amd64_edac: make driver loading more robust

Currently, the module does not initialize fully when the DIMMs aren't
ECC but remains still loaded. Propagate the error when no instance of
the driver is properly initialized and prevent further loading.

Reorganize and polish error handling in amd64_edac_init() while at it.

Signed-off-by: Borislav Petkov <[email protected]>
---
drivers/edac/amd64_edac.c | 23 ++++++++++++++++-------
1 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index fb0d36b..a8af27a 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -3014,25 +3014,29 @@ static void amd64_setup_pci_device(void)
static int __init amd64_edac_init(void)
{
int nb, err = -ENODEV;
+ bool load_ok = false;

edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n");

opstate_init();

if (cache_k8_northbridges() < 0)
- return err;
+ goto err_ret;

msrs = msrs_alloc();
+ if (!msrs)
+ goto err_ret;

err = pci_register_driver(&amd64_pci_driver);
if (err)
- return err;
+ goto err_pci;

/*
* At this point, the array 'pvt_lookup[]' contains pointers to alloc'd
* amd64_pvt structs. These will be used in the 2nd stage init function
* to finish initialization of the MC instances.
*/
+ err = -ENODEV;
for (nb = 0; nb < num_k8_northbridges; nb++) {
if (!pvt_lookup[nb])
continue;
@@ -3040,16 +3044,21 @@ static int __init amd64_edac_init(void)
err = amd64_init_2nd_stage(pvt_lookup[nb]);
if (err)
goto err_2nd_stage;
- }

- amd64_setup_pci_device();
+ load_ok = true;
+ }

- return 0;
+ if (load_ok) {
+ amd64_setup_pci_device();
+ return 0;
+ }

err_2nd_stage:
- debugf0("2nd stage failed\n");
pci_unregister_driver(&amd64_pci_driver);
-
+err_pci:
+ msrs_free(msrs);
+ msrs = NULL;
+err_ret:
return err;
}

--
1.6.5.4

Subject: [PATCH 4/6] amd64_edac: fix forcing module load/unload

Clear the override flag after force-loading the module.

Signed-off-by: Borislav Petkov <[email protected]>
---
drivers/edac/amd64_edac.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index a8af27a..63c04d3 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2690,9 +2690,8 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt)
amd64_printk(KERN_WARNING, "%s", ecc_warning);
return -ENODEV;
}
- } else
- /* CLEAR the override, since BIOS controlled it */
ecc_enable_override = 0;
+ }

return 0;
}
--
1.6.5.4

Subject: [PATCH 5/6] amd64_edac: restrict PCI config space access

Do not access F2x19[0,4] on K8 since they're undefined there.

Signed-off-by: Borislav Petkov <[email protected]>
---
drivers/edac/amd64_edac.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 63c04d3..c5facd9 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2349,7 +2349,7 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt)
amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0);
amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0);

- if (!dct_ganging_enabled(pvt)) {
+ if (!dct_ganging_enabled(pvt) && boot_cpu_data.x86 >= 0x10) {
amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1);
amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_1, &pvt->dchr1);
}
--
1.6.5.4

Subject: [PATCH 6/6] edac, pci: remove pesky debug printk

Do not spam the logs needlessly with the sole info that
edac_pci_dev_parity_clear is being called.

Signed-off-by: Borislav Petkov <[email protected]>
---
drivers/edac/edac_pci_sysfs.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index 422728c..fb60a87 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -534,8 +534,6 @@ 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 */
--
1.6.5.4