Skip to content

Commit

Permalink
Merge tag 'edac_for_5.5' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/ras/ras

Pull EDAC updates from Borislav Petkov:
 "A lot of changes this time around, details below.

  From the next cycle onwards, we'll switch the EDAC tree to topic
  branches (instead of a single edac-for-next branch) which should make
  the changes handling more flexible, hopefully. We'll see.

  Summary:

   - Rework error logging functions to accept a count of errors
     parameter (Hanna Hawa)

   - Part one of substantial EDAC core + ghes_edac driver cleanup
     (Robert Richter)

   - Print additional useful logging information in skx_* (Tony Luck)

   - Improve amd64_edac hw detection + cleanups (Yazen Ghannam)

   - Misc cleanups, fixes and code improvements"

* tag 'edac_for_5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras: (35 commits)
  EDAC/altera: Use the Altera System Manager driver
  EDAC/altera: Cleanup the ECC Manager
  EDAC/altera: Use fast register IO for S10 IRQs
  EDAC/ghes: Do not warn when incrementing refcount on 0
  EDAC/Documentation: Describe CPER module definition and DIMM ranks
  EDAC: Unify the mc_event tracepoint call
  EDAC/ghes: Remove intermediate buffer pvt->detail_location
  EDAC/ghes: Fix grain calculation
  EDAC/ghes: Use standard kernel macros for page calculations
  EDAC: Remove misleading comment in struct edac_raw_error_desc
  EDAC/mc: Reduce indentation level in edac_mc_handle_error()
  EDAC/mc: Remove needless zero string termination
  EDAC/mc: Do not BUG_ON() in edac_mc_alloc()
  EDAC: Introduce an mci_for_each_dimm() iterator
  EDAC: Remove EDAC_DIMM_OFF() macro
  EDAC: Replace EDAC_DIMM_PTR() macro with edac_get_dimm() function
  EDAC/amd64: Get rid of the ECC disabled long message
  EDAC/ghes: Fix locking and memory barrier issues
  EDAC/amd64: Check for memory before fully initializing an instance
  EDAC/amd64: Use cached data when checking for ECC
  ...
  • Loading branch information
torvalds committed Nov 26, 2019
2 parents 752272f + 5781823 commit 9c91e6a
Show file tree
Hide file tree
Showing 25 changed files with 555 additions and 633 deletions.
31 changes: 19 additions & 12 deletions Documentation/admin-guide/ras.rst
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,12 @@ There can be multiple csrows and multiple channels.

.. [#f4] Nowadays, the term DIMM (Dual In-line Memory Module) is widely
used to refer to a memory module, although there are other memory
packaging alternatives, like SO-DIMM, SIMM, etc. Along this document,
and inside the EDAC system, the term "dimm" is used for all memory
modules, even when they use a different kind of packaging.
packaging alternatives, like SO-DIMM, SIMM, etc. The UEFI
specification (Version 2.7) defines a memory module in the Common
Platform Error Record (CPER) section to be an SMBIOS Memory Device
(Type 17). Along this document, and inside the EDAC subsystem, the term
"dimm" is used for all memory modules, even when they use a
different kind of packaging.
Memory controllers allow for several csrows, with 8 csrows being a
typical value. Yet, the actual number of csrows depends on the layout of
Expand All @@ -349,12 +352,14 @@ controllers. The following example will assume 2 channels:
| | ``ch0`` | ``ch1`` |
+============+===========+===========+
| ``csrow0`` | DIMM_A0 | DIMM_B0 |
+------------+ | |
| ``csrow1`` | | |
| | rank0 | rank0 |
+------------+ - | - |
| ``csrow1`` | rank1 | rank1 |
+------------+-----------+-----------+
| ``csrow2`` | DIMM_A1 | DIMM_B1 |
+------------+ | |
| ``csrow3`` | | |
| | rank0 | rank0 |
+------------+ - | - |
| ``csrow3`` | rank1 | rank1 |
+------------+-----------+-----------+

In the above example, there are 4 physical slots on the motherboard
Expand All @@ -374,11 +379,13 @@ which the memory DIMM is placed. Thus, when 1 DIMM is placed in each
Channel, the csrows cross both DIMMs.

Memory DIMMs come single or dual "ranked". A rank is a populated csrow.
Thus, 2 single ranked DIMMs, placed in slots DIMM_A0 and DIMM_B0 above
will have just one csrow (csrow0). csrow1 will be empty. On the other
hand, when 2 dual ranked DIMMs are similarly placed, then both csrow0
and csrow1 will be populated. The pattern repeats itself for csrow2 and
csrow3.
In the example above 2 dual ranked DIMMs are similarly placed. Thus,
both csrow0 and csrow1 are populated. On the other hand, when 2 single
ranked DIMMs are placed in slots DIMM_A0 and DIMM_B0, then they will
have just one csrow (csrow0) and csrow1 will be empty. The pattern
repeats itself for csrow2 and csrow3. Also note that some memory
controllers don't have any logic to identify the memory module, see
``rankX`` directories below.

The representation of the above is reflected in the directory
tree in EDAC's sysfs interface. Starting in directory
Expand Down
152 changes: 9 additions & 143 deletions drivers/edac/altera_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/kernel.h>
#include <linux/mfd/altera-sysmgr.h>
#include <linux/mfd/syscon.h>
#include <linux/notifier.h>
#include <linux/of_address.h>
Expand Down Expand Up @@ -275,7 +276,6 @@ static int a10_unmask_irq(struct platform_device *pdev, u32 mask)
return ret;
}

static int socfpga_is_a10(void);
static int altr_sdram_probe(struct platform_device *pdev)
{
const struct of_device_id *id;
Expand Down Expand Up @@ -399,7 +399,7 @@ static int altr_sdram_probe(struct platform_device *pdev)
goto err;

/* Only the Arria10 has separate IRQs */
if (socfpga_is_a10()) {
if (of_machine_is_compatible("altr,socfpga-arria10")) {
/* Arria10 specific initialization */
res = a10_init(mc_vbase);
if (res < 0)
Expand Down Expand Up @@ -502,68 +502,6 @@ module_platform_driver(altr_sdram_edac_driver);

#endif /* CONFIG_EDAC_ALTERA_SDRAM */

/**************** Stratix 10 EDAC Memory Controller Functions ************/

/**
* s10_protected_reg_write
* Write to a protected SMC register.
* @context: Not used.
* @reg: Address of register
* @value: Value to write
* Return: INTEL_SIP_SMC_STATUS_OK (0) on success
* INTEL_SIP_SMC_REG_ERROR on error
* INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported
*/
static int s10_protected_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct arm_smccc_res result;
unsigned long offset = (unsigned long)context;

arm_smccc_smc(INTEL_SIP_SMC_REG_WRITE, offset + reg, val, 0, 0,
0, 0, 0, &result);

return (int)result.a0;
}

/**
* s10_protected_reg_read
* Read the status of a protected SMC register
* @context: Not used.
* @reg: Address of register
* @value: Value read.
* Return: INTEL_SIP_SMC_STATUS_OK (0) on success
* INTEL_SIP_SMC_REG_ERROR on error
* INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported
*/
static int s10_protected_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
struct arm_smccc_res result;
unsigned long offset = (unsigned long)context;

arm_smccc_smc(INTEL_SIP_SMC_REG_READ, offset + reg, 0, 0, 0,
0, 0, 0, &result);

*val = (unsigned int)result.a1;

return (int)result.a0;
}

static const struct regmap_config s10_sdram_regmap_cfg = {
.name = "s10_ddr",
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0xffd12228,
.reg_read = s10_protected_reg_read,
.reg_write = s10_protected_reg_write,
.use_single_read = true,
.use_single_write = true,
};

/************** </Stratix10 EDAC Memory Controller Functions> ***********/

/************************* EDAC Parent Probe *************************/

static const struct of_device_id altr_edac_device_of_match[];
Expand Down Expand Up @@ -1008,16 +946,6 @@ static int __maybe_unused altr_init_memory_port(void __iomem *ioaddr, int port)
return ret;
}

static int socfpga_is_a10(void)
{
return of_machine_is_compatible("altr,socfpga-arria10");
}

static int socfpga_is_s10(void)
{
return of_machine_is_compatible("altr,socfpga-stratix10");
}

static __init int __maybe_unused
altr_init_a10_ecc_block(struct device_node *np, u32 irq_mask,
u32 ecc_ctrl_en_mask, bool dual_port)
Expand All @@ -1033,34 +961,10 @@ altr_init_a10_ecc_block(struct device_node *np, u32 irq_mask,
/* Get the ECC Manager - parent of the device EDACs */
np_eccmgr = of_get_parent(np);

if (socfpga_is_a10()) {
ecc_mgr_map = syscon_regmap_lookup_by_phandle(np_eccmgr,
"altr,sysmgr-syscon");
} else {
struct device_node *sysmgr_np;
struct resource res;
uintptr_t base;

sysmgr_np = of_parse_phandle(np_eccmgr,
"altr,sysmgr-syscon", 0);
if (!sysmgr_np) {
edac_printk(KERN_ERR, EDAC_DEVICE,
"Unable to find altr,sysmgr-syscon\n");
return -ENODEV;
}

if (of_address_to_resource(sysmgr_np, 0, &res)) {
of_node_put(sysmgr_np);
return -ENOMEM;
}
ecc_mgr_map =
altr_sysmgr_regmap_lookup_by_phandle(np_eccmgr,
"altr,sysmgr-syscon");

/* Need physical address for SMCC call */
base = res.start;

ecc_mgr_map = regmap_init(NULL, NULL, (void *)base,
&s10_sdram_regmap_cfg);
of_node_put(sysmgr_np);
}
of_node_put(np_eccmgr);
if (IS_ERR(ecc_mgr_map)) {
edac_printk(KERN_ERR, EDAC_DEVICE,
Expand Down Expand Up @@ -1125,9 +1029,6 @@ static int __init __maybe_unused altr_init_a10_ecc_device_type(char *compat)
int irq;
struct device_node *child, *np;

if (!socfpga_is_a10() && !socfpga_is_s10())
return -ENODEV;

np = of_find_compatible_node(NULL, NULL,
"altr,socfpga-a10-ecc-manager");
if (!np) {
Expand Down Expand Up @@ -2178,33 +2079,9 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, edac);
INIT_LIST_HEAD(&edac->a10_ecc_devices);

if (socfpga_is_a10()) {
edac->ecc_mgr_map =
syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"altr,sysmgr-syscon");
} else {
struct device_node *sysmgr_np;
struct resource res;
uintptr_t base;

sysmgr_np = of_parse_phandle(pdev->dev.of_node,
"altr,sysmgr-syscon", 0);
if (!sysmgr_np) {
edac_printk(KERN_ERR, EDAC_DEVICE,
"Unable to find altr,sysmgr-syscon\n");
return -ENODEV;
}

if (of_address_to_resource(sysmgr_np, 0, &res))
return -ENOMEM;

/* Need physical address for SMCC call */
base = res.start;

edac->ecc_mgr_map = devm_regmap_init(&pdev->dev, NULL,
(void *)base,
&s10_sdram_regmap_cfg);
}
edac->ecc_mgr_map =
altr_sysmgr_regmap_lookup_by_phandle(pdev->dev.of_node,
"altr,sysmgr-syscon");

if (IS_ERR(edac->ecc_mgr_map)) {
edac_printk(KERN_ERR, EDAC_DEVICE,
Expand Down Expand Up @@ -2270,18 +2147,7 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
if (!of_device_is_available(child))
continue;

if (of_device_is_compatible(child, "altr,socfpga-a10-l2-ecc") ||
of_device_is_compatible(child, "altr,socfpga-a10-ocram-ecc") ||
of_device_is_compatible(child, "altr,socfpga-eth-mac-ecc") ||
of_device_is_compatible(child, "altr,socfpga-nand-ecc") ||
of_device_is_compatible(child, "altr,socfpga-dma-ecc") ||
of_device_is_compatible(child, "altr,socfpga-usb-ecc") ||
of_device_is_compatible(child, "altr,socfpga-qspi-ecc") ||
#ifdef CONFIG_EDAC_ALTERA_SDRAM
of_device_is_compatible(child, "altr,sdram-edac-s10") ||
#endif
of_device_is_compatible(child, "altr,socfpga-sdmmc-ecc"))

if (of_match_node(altr_edac_a10_device_of_match, child))
altr_edac_a10_device_add(edac, child);

#ifdef CONFIG_EDAC_ALTERA_SDRAM
Expand Down
Loading

0 comments on commit 9c91e6a

Please sign in to comment.