History

Merge tag 'edac_for_5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras

Pull EDAC updates from Borislav Petkov: "The new thing this time around is that we have three maintainers now and a new, old repo. New because it is new for the EDAC tree which is hosted there from now on and old because it is Tony's and mine's old RAS repo which we still use occasionally when the stuff isn't in tip. Summary: - EDAC tree has three maintainers and one new designated reviewer now, so that the work can scale better. - New driver for Mellanox' BlueField SoC DDR controller (Shravan Kumar Ramani) - AMD Rome support in amd64_edac (Yazen Ghannam and Isaac Vaughn) - Misc fixes, cleanups and code improvements" * tag 'edac_for_5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras: EDAC/amd64: Add PCI device IDs for family 17h, model 70h MAINTAINERS: Add Robert as a EDAC reviewer EDAC/mc_sysfs: Make debug messages consistent EDAC/mc_sysfs: Remove pointless gotos EDAC: Prefer 'unsigned int' to bare use of 'unsigned' EDAC/amd64: Support asymmetric dual-rank DIMMs EDAC/amd64: Cache secondary Chip Select registers EDAC/amd64: Decode syndrome before translating address EDAC/amd64: Find Chip Select memory size using Address Mask EDAC/amd64: Initialize DIMM info for systems with more than two channels EDAC/amd64: Recognize DRAM device type ECC capability EDAC/amd64: Support more than two controllers for chip selects handling EDAC/mc: Cleanup _edac_mc_free() code EDAC, pnd2: Fix ioremap() size in dnv_rd_reg() EDAC, mellanox: Add ECC support for BlueField DDR4 EDAC/altera: Use the proper type for the IRQ status bits EDAC/mc: Fix grain_bits calculation edac: altera: Move Stratix10 SDRAM ECC to peripheral MAINTAINERS: update EDAC entry to reflect current tree and maintainers

Linus Torvalds committed 7 years ago

Commit ff881842 parents a7bd4bc 3e443eb15 files · +803 −226Browse files

Unified · Split

15 files
  1. MAINTAINERS +8 −2
  2. drivers/edac/Kconfig +7 −0
  3. drivers/edac/Makefile +1 −0
  4. drivers/edac/altera_edac.c +53 −5
  5. drivers/edac/altera_edac.h +24 −1
  6. drivers/edac/amd64_edac.c +249 −122
  7. drivers/edac/amd64_edac.h +12 −3
  8. drivers/edac/bluefield_edac.c +356 −0
  9. drivers/edac/edac_mc.c +28 −25
  10. drivers/edac/edac_mc.h +3 −3
  11. drivers/edac/edac_mc_sysfs.c +41 −51
  12. drivers/edac/ghes_edac.c +1 −1
  13. drivers/edac/i5100_edac.c +9 −7
  14. drivers/edac/pnd2_edac.c +6 −1
  15. include/linux/edac.h +5 −5
MAINTAINERS+8−2
@@ -5761,6 +5761,11 @@ S: Supported · 5760 unmodified lines
5761F: drivers/edac/aspeed_edac.c5761F: drivers/edac/aspeed_edac.c
5762F: Documentation/devicetree/bindings/edac/aspeed-sdram-edac.txt5762F: Documentation/devicetree/bindings/edac/aspeed-sdram-edac.txt
5763 5763
5764EDAC-BLUEFIELD
5765M: Shravan Kumar Ramani <sramani@mellanox.com>
5766S: Supported
5767F: drivers/edac/bluefield_edac.c
5768
5764EDAC-CALXEDA5769EDAC-CALXEDA
5765M: Robert Richter <rric@kernel.org>5770M: Robert Richter <rric@kernel.org>
5766L: linux-edac@vger.kernel.org5771L: linux-edac@vger.kernel.org
@@ -5785,10 +5790,11 @@ F: drivers/edac/thunderx_edac* · 18 unmodified lines
5785EDAC-CORE5790EDAC-CORE
5786M: Borislav Petkov <bp@alien8.de>5791M: Borislav Petkov <bp@alien8.de>
5787M: Mauro Carvalho Chehab <mchehab@kernel.org>5792M: Mauro Carvalho Chehab <mchehab@kernel.org>
5793M: Tony Luck <tony.luck@intel.com>
5788R: James Morse <james.morse@arm.com>5794R: James Morse <james.morse@arm.com>
5795R: Robert Richter <rrichter@marvell.com>
5789L: linux-edac@vger.kernel.org5796L: linux-edac@vger.kernel.org
5790T: git git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git for-next5797T: git git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras.git edac-for-next
5791T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git linux_next
5792S: Supported5798S: Supported
5793F: Documentation/admin-guide/ras.rst5799F: Documentation/admin-guide/ras.rst
5794F: Documentation/driver-api/edac.rst5800F: Documentation/driver-api/edac.rst
drivers/edac/Kconfig+7−0
@@ -510,4 +510,11 @@ config EDAC_ASPEED · 509 unmodified lines
510 First, ECC must be configured in the bootloader. Then, this driver510 First, ECC must be configured in the bootloader. Then, this driver
511 will expose error counters via the EDAC kernel framework.511 will expose error counters via the EDAC kernel framework.
512 512
513config EDAC_BLUEFIELD
514 tristate "Mellanox BlueField Memory ECC"
515 depends on ARM64 && ((MELLANOX_PLATFORM && ACPI) || COMPILE_TEST)
516 help
517 Support for error detection and correction on the
518 Mellanox BlueField SoCs.
519
513endif # EDAC520endif # EDAC
drivers/edac/Makefile+1−0
@@ -85,3 +85,4 @@ obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o · 84 unmodified lines
85obj-$(CONFIG_EDAC_TI) += ti_edac.o85obj-$(CONFIG_EDAC_TI) += ti_edac.o
86obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o86obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o
87obj-$(CONFIG_EDAC_ASPEED) += aspeed_edac.o87obj-$(CONFIG_EDAC_ASPEED) += aspeed_edac.o
88obj-$(CONFIG_EDAC_BLUEFIELD) += bluefield_edac.o
drivers/edac/altera_edac.c+53−5
@@ -222,7 +222,6 @@ static unsigned long get_total_mem(void) · 221 unmodified lines
222static const struct of_device_id altr_sdram_ctrl_of_match[] = {222static const struct of_device_id altr_sdram_ctrl_of_match[] = {
223 { .compatible = "altr,sdram-edac", .data = &c5_data},223 { .compatible = "altr,sdram-edac", .data = &c5_data},
224 { .compatible = "altr,sdram-edac-a10", .data = &a10_data},224 { .compatible = "altr,sdram-edac-a10", .data = &a10_data},
225 { .compatible = "altr,sdram-edac-s10", .data = &a10_data},
226 {},225 {},
227};226};
228MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match);227MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match);
@@ -1170,6 +1169,24 @@ static int __init __maybe_unused altr_init_a10_ecc_device_type(char *compat) · 941 unmodified lines
1170 return 0;1169 return 0;
1171}1170}
1172 1171
1172/*********************** SDRAM EDAC Device Functions *********************/
1173
1174#ifdef CONFIG_EDAC_ALTERA_SDRAM
1175
1176static const struct edac_device_prv_data s10_sdramecc_data = {
1177 .setup = altr_check_ecc_deps,
1178 .ce_clear_mask = ALTR_S10_ECC_SERRPENA,
1179 .ue_clear_mask = ALTR_S10_ECC_DERRPENA,
1180 .ecc_enable_mask = ALTR_S10_ECC_EN,
1181 .ecc_en_ofst = ALTR_S10_ECC_CTRL_SDRAM_OFST,
1182 .ce_set_mask = ALTR_S10_ECC_TSERRA,
1183 .ue_set_mask = ALTR_S10_ECC_TDERRA,
1184 .set_err_ofst = ALTR_S10_ECC_INTTEST_OFST,
1185 .ecc_irq_handler = altr_edac_a10_ecc_irq,
1186 .inject_fops = &altr_edac_a10_device_inject_fops,
1187};
1188#endif /* CONFIG_EDAC_ALTERA_SDRAM */
1189
1173/*********************** OCRAM EDAC Device Functions *********************/1190/*********************** OCRAM EDAC Device Functions *********************/
1174 1191
1175#ifdef CONFIG_EDAC_ALTERA_OCRAM1192#ifdef CONFIG_EDAC_ALTERA_OCRAM
@@ -1758,6 +1775,9 @@ static const struct of_device_id altr_edac_a10_device_of_match[] = { · 582 unmodified lines
1758#endif1775#endif
1759#ifdef CONFIG_EDAC_ALTERA_SDMMC1776#ifdef CONFIG_EDAC_ALTERA_SDMMC
1760 { .compatible = "altr,socfpga-sdmmc-ecc", .data = &a10_sdmmcecca_data },1777 { .compatible = "altr,socfpga-sdmmc-ecc", .data = &a10_sdmmcecca_data },
1778#endif
1779#ifdef CONFIG_EDAC_ALTERA_SDRAM
1780 { .compatible = "altr,sdram-edac-s10", .data = &s10_sdramecc_data },
1761#endif1781#endif
1762 {},1782 {},
1763};1783};
@@ -1866,6 +1886,7 @@ static void altr_edac_a10_irq_handler(struct irq_desc *desc) · 102 unmodified lines
1866 struct altr_arria10_edac *edac = irq_desc_get_handler_data(desc);1886 struct altr_arria10_edac *edac = irq_desc_get_handler_data(desc);
1867 struct irq_chip *chip = irq_desc_get_chip(desc);1887 struct irq_chip *chip = irq_desc_get_chip(desc);
1868 int irq = irq_desc_get_irq(desc);1888 int irq = irq_desc_get_irq(desc);
1889 unsigned long bits;
1869 1890
1870 dberr = (irq == edac->db_irq) ? 1 : 0;1891 dberr = (irq == edac->db_irq) ? 1 : 0;
1871 sm_offset = dberr ? A10_SYSMGR_ECC_INTSTAT_DERR_OFST :1892 sm_offset = dberr ? A10_SYSMGR_ECC_INTSTAT_DERR_OFST :
@@ -1875,7 +1896,8 @@ static void altr_edac_a10_irq_handler(struct irq_desc *desc) · 3 unmodified lines
1875 1896
1876 regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status);1897 regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status);
1877 1898
1878 for_each_set_bit(bit, (unsigned long *)&irq_status, 32) {1899 bits = irq_status;
1900 for_each_set_bit(bit, &bits, 32) {
1879 irq = irq_linear_revmap(edac->domain, dberr * 32 + bit);1901 irq = irq_linear_revmap(edac->domain, dberr * 32 + bit);
1880 if (irq)1902 if (irq)
1881 generic_handle_irq(irq);1903 generic_handle_irq(irq);
@@ -1889,6 +1911,10 @@ static int validate_parent_available(struct device_node *np) · 7 unmodified lines
1889 struct device_node *parent;1911 struct device_node *parent;
1890 int ret = 0;1912 int ret = 0;
1891 1913
1914 /* SDRAM must be present for Linux (implied parent) */
1915 if (of_device_is_compatible(np, "altr,sdram-edac-s10"))
1916 return 0;
1917
1892 /* Ensure parent device is enabled if parent node exists */1918 /* Ensure parent device is enabled if parent node exists */
1893 parent = of_parse_phandle(np, "altr,ecc-parent", 0);1919 parent = of_parse_phandle(np, "altr,ecc-parent", 0);
1894 if (parent && !of_device_is_available(parent))1920 if (parent && !of_device_is_available(parent))
@@ -1898,6 +1924,22 @@ static int validate_parent_available(struct device_node *np) · 3 unmodified lines
1898 return ret;1924 return ret;
1899}1925}
1900 1926
1927static int get_s10_sdram_edac_resource(struct device_node *np,
1928 struct resource *res)
1929{
1930 struct device_node *parent;
1931 int ret;
1932
1933 parent = of_parse_phandle(np, "altr,sdr-syscon", 0);
1934 if (!parent)
1935 return -ENODEV;
1936
1937 ret = of_address_to_resource(parent, 0, res);
1938 of_node_put(parent);
1939
1940 return ret;
1941}
1942
1901static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,1943static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
1902 struct device_node *np)1944 struct device_node *np)
1903{1945{
@@ -1925,7 +1967,11 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac, · 21 unmodified lines
1925 if (!devres_open_group(edac->dev, altr_edac_a10_device_add, GFP_KERNEL))1967 if (!devres_open_group(edac->dev, altr_edac_a10_device_add, GFP_KERNEL))
1926 return -ENOMEM;1968 return -ENOMEM;
1927 1969
1928 rc = of_address_to_resource(np, 0, &res);1970 if (of_device_is_compatible(np, "altr,sdram-edac-s10"))
1971 rc = get_s10_sdram_edac_resource(np, &res);
1972 else
1973 rc = of_address_to_resource(np, 0, &res);
1974
1929 if (rc < 0) {1975 if (rc < 0) {
1930 edac_printk(KERN_ERR, EDAC_DEVICE,1976 edac_printk(KERN_ERR, EDAC_DEVICE,
1931 "%s: no resource address\n", ecc_name);1977 "%s: no resource address\n", ecc_name);
@@ -2231,13 +2277,15 @@ static int altr_edac_a10_probe(struct platform_device *pdev) · 299 unmodified lines
2231 of_device_is_compatible(child, "altr,socfpga-dma-ecc") ||2277 of_device_is_compatible(child, "altr,socfpga-dma-ecc") ||
2232 of_device_is_compatible(child, "altr,socfpga-usb-ecc") ||2278 of_device_is_compatible(child, "altr,socfpga-usb-ecc") ||
2233 of_device_is_compatible(child, "altr,socfpga-qspi-ecc") ||2279 of_device_is_compatible(child, "altr,socfpga-qspi-ecc") ||
2280#ifdef CONFIG_EDAC_ALTERA_SDRAM
2281 of_device_is_compatible(child, "altr,sdram-edac-s10") ||
2282#endif
2234 of_device_is_compatible(child, "altr,socfpga-sdmmc-ecc"))2283 of_device_is_compatible(child, "altr,socfpga-sdmmc-ecc"))
2235 2284
2236 altr_edac_a10_device_add(edac, child);2285 altr_edac_a10_device_add(edac, child);
2237 2286
2238#ifdef CONFIG_EDAC_ALTERA_SDRAM2287#ifdef CONFIG_EDAC_ALTERA_SDRAM
2239 else if ((of_device_is_compatible(child, "altr,sdram-edac-a10")) ||2288 else if (of_device_is_compatible(child, "altr,sdram-edac-a10"))
2240 (of_device_is_compatible(child, "altr,sdram-edac-s10")))
2241 of_platform_populate(pdev->dev.of_node,2289 of_platform_populate(pdev->dev.of_node,
2242 altr_sdram_ctrl_of_match,2290 altr_sdram_ctrl_of_match,
2243 NULL, &pdev->dev);2291 NULL, &pdev->dev);
drivers/edac/altera_edac.h+24−1
@@ -289,6 +289,29 @@ struct altr_sdram_mc_data { · 288 unmodified lines
289#define ALTR_A10_ECC_INIT_WATCHDOG_10US 10000289#define ALTR_A10_ECC_INIT_WATCHDOG_10US 10000
290 290
291/************* Stratix10 Defines **************/291/************* Stratix10 Defines **************/
292#define ALTR_S10_ECC_CTRL_SDRAM_OFST 0x00
293#define ALTR_S10_ECC_EN BIT(0)
294
295#define ALTR_S10_ECC_ERRINTEN_OFST 0x10
296#define ALTR_S10_ECC_ERRINTENS_OFST 0x14
297#define ALTR_S10_ECC_ERRINTENR_OFST 0x18
298#define ALTR_S10_ECC_SERRINTEN BIT(0)
299
300#define ALTR_S10_ECC_INTMODE_OFST 0x1C
301#define ALTR_S10_ECC_INTMODE BIT(0)
302
303#define ALTR_S10_ECC_INTSTAT_OFST 0x20
304#define ALTR_S10_ECC_SERRPENA BIT(0)
305#define ALTR_S10_ECC_DERRPENA BIT(8)
306#define ALTR_S10_ECC_ERRPENA_MASK (ALTR_S10_ECC_SERRPENA | \
307 ALTR_S10_ECC_DERRPENA)
308
309#define ALTR_S10_ECC_INTTEST_OFST 0x24
310#define ALTR_S10_ECC_TSERRA BIT(0)
311#define ALTR_S10_ECC_TDERRA BIT(8)
312#define ALTR_S10_ECC_TSERRB BIT(16)
313#define ALTR_S10_ECC_TDERRB BIT(24)
314
292#define ALTR_S10_DERR_ADDRA_OFST 0x2C315#define ALTR_S10_DERR_ADDRA_OFST 0x2C
293 316
294/* Stratix10 ECC Manager Defines */317/* Stratix10 ECC Manager Defines */
@@ -300,7 +323,7 @@ struct altr_sdram_mc_data { · 5 unmodified lines
300#define S10_SYSMGR_UE_ADDR_OFST 0x224323#define S10_SYSMGR_UE_ADDR_OFST 0x224
301 324
302#define S10_DDR0_IRQ_MASK BIT(16)325#define S10_DDR0_IRQ_MASK BIT(16)
303#define S10_DBE_IRQ_MASK 0x3FE326#define S10_DBE_IRQ_MASK 0x3FFFE
304 327
305/* Define ECC Block Offsets for peripherals */328/* Define ECC Block Offsets for peripherals */
306#define ECC_BLK_ADDRESS_OFST 0x40329#define ECC_BLK_ADDRESS_OFST 0x40
drivers/edac/amd64_edac.c+249−122
@@ -788,51 +788,45 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) · 787 unmodified lines
788 (dclr & BIT(15)) ? "yes" : "no");788 (dclr & BIT(15)) ? "yes" : "no");
789}789}
790 790
791/*791#define CS_EVEN_PRIMARY BIT(0)
792 * The Address Mask should be a contiguous set of bits in the non-interleaved792#define CS_ODD_PRIMARY BIT(1)
793 * case. So to check for CS interleaving, find the most- and least-significant793#define CS_EVEN_SECONDARY BIT(2)
794 * bits of the mask, generate a contiguous bitmask, and compare the two.794#define CS_ODD_SECONDARY BIT(3)
795 */795
796static bool f17_cs_interleaved(struct amd64_pvt *pvt, u8 ctrl, int cs)796#define CS_EVEN (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY)
797#define CS_ODD (CS_ODD_PRIMARY | CS_ODD_SECONDARY)
798
799static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
797{800{
798 u32 mask = pvt->csels[ctrl].csmasks[cs >> 1];801 int cs_mode = 0;
799 u32 msb = fls(mask) - 1, lsb = ffs(mask) - 1;
800 u32 test_mask = GENMASK(msb, lsb);
801 802
802 edac_dbg(1, "mask=0x%08x test_mask=0x%08x\n", mask, test_mask);803 if (csrow_enabled(2 * dimm, ctrl, pvt))
804 cs_mode |= CS_EVEN_PRIMARY;
803 805
804 return mask ^ test_mask;806 if (csrow_enabled(2 * dimm + 1, ctrl, pvt))
807 cs_mode |= CS_ODD_PRIMARY;
808
809 /* Asymmetric dual-rank DIMM support. */
810 if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
811 cs_mode |= CS_ODD_SECONDARY;
812
813 return cs_mode;
805}814}
806 815
807static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)816static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
808{817{
809 int dimm, size0, size1, cs0, cs1;818 int dimm, size0, size1, cs0, cs1, cs_mode;
810 819
811 edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);820 edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);
812 821
813 for (dimm = 0; dimm < 4; dimm++) {822 for (dimm = 0; dimm < 2; dimm++) {
814 size0 = 0;
815 cs0 = dimm * 2;823 cs0 = dimm * 2;
816
817 if (csrow_enabled(cs0, ctrl, pvt))
818 size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0);
819
820 size1 = 0;
821 cs1 = dimm * 2 + 1;824 cs1 = dimm * 2 + 1;
822 825
823 if (csrow_enabled(cs1, ctrl, pvt)) {826 cs_mode = f17_get_cs_mode(dimm, ctrl, pvt);
824 /*827
825 * CS interleaving is only supported if both CSes have828 size0 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs0);
826 * the same amount of memory. Because they are829 size1 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs1);
827 * interleaved, it will look like both CSes have the
828 * full amount of memory. Save the size for both as
829 * half the amount we found on CS0, if interleaved.
830 */
831 if (f17_cs_interleaved(pvt, ctrl, cs1))
832 size1 = size0 = (size0 >> 1);
833 else
834 size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1);
835 }
836 830
837 amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",831 amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
838 cs0, size0,832 cs0, size0,
@@ -942,89 +936,119 @@ static void prep_chip_selects(struct amd64_pvt *pvt) · 103 unmodified lines
942 } else if (pvt->fam == 0x15 && pvt->model == 0x30) {936 } else if (pvt->fam == 0x15 && pvt->model == 0x30) {
943 pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4;937 pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4;
944 pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2;938 pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2;
939 } else if (pvt->fam >= 0x17) {
940 int umc;
941
942 for_each_umc(umc) {
943 pvt->csels[umc].b_cnt = 4;
944 pvt->csels[umc].m_cnt = 2;
945 }
946
945 } else {947 } else {
946 pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;948 pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
947 pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4;949 pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4;
948 }950 }
949}951}
950 952
953static void read_umc_base_mask(struct amd64_pvt *pvt)
954{
955 u32 umc_base_reg, umc_base_reg_sec;
956 u32 umc_mask_reg, umc_mask_reg_sec;
957 u32 base_reg, base_reg_sec;
958 u32 mask_reg, mask_reg_sec;
959 u32 *base, *base_sec;
960 u32 *mask, *mask_sec;
961 int cs, umc;
962
963 for_each_umc(umc) {
964 umc_base_reg = get_umc_base(umc) + UMCCH_BASE_ADDR;
965 umc_base_reg_sec = get_umc_base(umc) + UMCCH_BASE_ADDR_SEC;
966
967 for_each_chip_select(cs, umc, pvt) {
968 base = &pvt->csels[umc].csbases[cs];
969 base_sec = &pvt->csels[umc].csbases_sec[cs];
970
971 base_reg = umc_base_reg + (cs * 4);
972 base_reg_sec = umc_base_reg_sec + (cs * 4);
973
974 if (!amd_smn_read(pvt->mc_node_id, base_reg, base))
975 edac_dbg(0, " DCSB%d[%d]=0x%08x reg: 0x%x\n",
976 umc, cs, *base, base_reg);
977
978 if (!amd_smn_read(pvt->mc_node_id, base_reg_sec, base_sec))
979 edac_dbg(0, " DCSB_SEC%d[%d]=0x%08x reg: 0x%x\n",
980 umc, cs, *base_sec, base_reg_sec);
981 }
982
983 umc_mask_reg = get_umc_base(umc) + UMCCH_ADDR_MASK;
984 umc_mask_reg_sec = get_umc_base(umc) + UMCCH_ADDR_MASK_SEC;
985
986 for_each_chip_select_mask(cs, umc, pvt) {
987 mask = &pvt->csels[umc].csmasks[cs];
988 mask_sec = &pvt->csels[umc].csmasks_sec[cs];
989
990 mask_reg = umc_mask_reg + (cs * 4);
991 mask_reg_sec = umc_mask_reg_sec + (cs * 4);
992
993 if (!amd_smn_read(pvt->mc_node_id, mask_reg, mask))
994 edac_dbg(0, " DCSM%d[%d]=0x%08x reg: 0x%x\n",
995 umc, cs, *mask, mask_reg);
996
997 if (!amd_smn_read(pvt->mc_node_id, mask_reg_sec, mask_sec))
998 edac_dbg(0, " DCSM_SEC%d[%d]=0x%08x reg: 0x%x\n",
999 umc, cs, *mask_sec, mask_reg_sec);
1000 }
1001 }
1002}
1003
951/*1004/*
952 * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask registers1005 * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask registers
953 */1006 */
954static void read_dct_base_mask(struct amd64_pvt *pvt)1007static void read_dct_base_mask(struct amd64_pvt *pvt)
955{1008{
956 int base_reg0, base_reg1, mask_reg0, mask_reg1, cs;1009 int cs;
957 1010
958 prep_chip_selects(pvt);1011 prep_chip_selects(pvt);
959 1012
960 if (pvt->umc) {1013 if (pvt->umc)
961 base_reg0 = get_umc_base(0) + UMCCH_BASE_ADDR;1014 return read_umc_base_mask(pvt);
962 base_reg1 = get_umc_base(1) + UMCCH_BASE_ADDR;
963 mask_reg0 = get_umc_base(0) + UMCCH_ADDR_MASK;
964 mask_reg1 = get_umc_base(1) + UMCCH_ADDR_MASK;
965 } else {
966 base_reg0 = DCSB0;
967 base_reg1 = DCSB1;
968 mask_reg0 = DCSM0;
969 mask_reg1 = DCSM1;
970 }
971 1015
972 for_each_chip_select(cs, 0, pvt) {1016 for_each_chip_select(cs, 0, pvt) {
973 int reg0 = base_reg0 + (cs * 4);1017 int reg0 = DCSB0 + (cs * 4);
974 int reg1 = base_reg1 + (cs * 4);1018 int reg1 = DCSB1 + (cs * 4);
975 u32 *base0 = &pvt->csels[0].csbases[cs];1019 u32 *base0 = &pvt->csels[0].csbases[cs];
976 u32 *base1 = &pvt->csels[1].csbases[cs];1020 u32 *base1 = &pvt->csels[1].csbases[cs];
977 1021
978 if (pvt->umc) {1022 if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0))
979 if (!amd_smn_read(pvt->mc_node_id, reg0, base0))1023 edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n",
980 edac_dbg(0, " DCSB0[%d]=0x%08x reg: 0x%x\n",1024 cs, *base0, reg0);
981 cs, *base0, reg0);
982 1025
983 if (!amd_smn_read(pvt->mc_node_id, reg1, base1))1026 if (pvt->fam == 0xf)
984 edac_dbg(0, " DCSB1[%d]=0x%08x reg: 0x%x\n",1027 continue;
985 cs, *base1, reg1);
986 } else {
987 if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0))
988 edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n",
989 cs, *base0, reg0);
990
991 if (pvt->fam == 0xf)
992 continue;
993 1028
994 if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1))1029 if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1))
995 edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n",1030 edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n",
996 cs, *base1, (pvt->fam == 0x10) ? reg11031 cs, *base1, (pvt->fam == 0x10) ? reg1
997 : reg0);1032 : reg0);
998 }
999 }1033 }
1000 1034
1001 for_each_chip_select_mask(cs, 0, pvt) {1035 for_each_chip_select_mask(cs, 0, pvt) {
1002 int reg0 = mask_reg0 + (cs * 4);1036 int reg0 = DCSM0 + (cs * 4);
1003 int reg1 = mask_reg1 + (cs * 4);1037 int reg1 = DCSM1 + (cs * 4);
1004 u32 *mask0 = &pvt->csels[0].csmasks[cs];1038 u32 *mask0 = &pvt->csels[0].csmasks[cs];
1005 u32 *mask1 = &pvt->csels[1].csmasks[cs];1039 u32 *mask1 = &pvt->csels[1].csmasks[cs];
1006 1040
1007 if (pvt->umc) {1041 if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0))
1008 if (!amd_smn_read(pvt->mc_node_id, reg0, mask0))1042 edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n",
1009 edac_dbg(0, " DCSM0[%d]=0x%08x reg: 0x%x\n",1043 cs, *mask0, reg0);
1010 cs, *mask0, reg0);
1011
1012 if (!amd_smn_read(pvt->mc_node_id, reg1, mask1))
1013 edac_dbg(0, " DCSM1[%d]=0x%08x reg: 0x%x\n",
1014 cs, *mask1, reg1);
1015 } else {
1016 if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0))
1017 edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n",
1018 cs, *mask0, reg0);
1019 1044
1020 if (pvt->fam == 0xf)1045 if (pvt->fam == 0xf)
1021 continue;1046 continue;
1022 1047
1023 if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1))1048 if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1))
1024 edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n",1049 edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n",
1025 cs, *mask1, (pvt->fam == 0x10) ? reg11050 cs, *mask1, (pvt->fam == 0x10) ? reg1
1026 : reg0);1051 : reg0);
1027 }
1028 }1052 }
1029}1053}
1030 1054
@@ -1556,18 +1580,58 @@ static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, · 525 unmodified lines
1556 return ddr3_cs_size(cs_mode, false);1580 return ddr3_cs_size(cs_mode, false);
1557}1581}
1558 1582
1559static int f17_base_addr_to_cs_size(struct amd64_pvt *pvt, u8 umc,1583static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
1560 unsigned int cs_mode, int csrow_nr)1584 unsigned int cs_mode, int csrow_nr)
1561{1585{
1562 u32 base_addr = pvt->csels[umc].csbases[csrow_nr];1586 u32 addr_mask_orig, addr_mask_deinterleaved;
1587 u32 msb, weight, num_zero_bits;
1588 int dimm, size = 0;
1563 1589
1564 /* Each mask is used for every two base addresses. */1590 /* No Chip Selects are enabled. */
1565 u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr >> 1];1591 if (!cs_mode)
1592 return size;
1566 1593
1567 /* Register [31:1] = Address [39:9]. Size is in kBs here. */1594 /* Requested size of an even CS but none are enabled. */
1568 u32 size = ((addr_mask >> 1) - (base_addr >> 1) + 1) >> 1;1595 if (!(cs_mode & CS_EVEN) && !(csrow_nr & 1))
1596 return size;
1569 1597
1570 edac_dbg(1, "BaseAddr: 0x%x, AddrMask: 0x%x\n", base_addr, addr_mask);1598 /* Requested size of an odd CS but none are enabled. */
1599 if (!(cs_mode & CS_ODD) && (csrow_nr & 1))
1600 return size;
1601
1602 /*
1603 * There is one mask per DIMM, and two Chip Selects per DIMM.
1604 * CS0 and CS1 -> DIMM0
1605 * CS2 and CS3 -> DIMM1
1606 */
1607 dimm = csrow_nr >> 1;
1608
1609 /* Asymmetric dual-rank DIMM support. */
1610 if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
1611 addr_mask_orig = pvt->csels[umc].csmasks_sec[dimm];
1612 else
1613 addr_mask_orig = pvt->csels[umc].csmasks[dimm];
1614
1615 /*
1616 * The number of zero bits in the mask is equal to the number of bits
1617 * in a full mask minus the number of bits in the current mask.
1618 *
1619 * The MSB is the number of bits in the full mask because BIT[0] is
1620 * always 0.
1621 */
1622 msb = fls(addr_mask_orig) - 1;
1623 weight = hweight_long(addr_mask_orig);
1624 num_zero_bits = msb - weight;
1625
1626 /* Take the number of zero bits off from the top of the mask. */
1627 addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);
1628
1629 edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
1630 edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig);
1631 edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);
1632
1633 /* Register [31:1] = Address [39:9]. Size is in kBs here. */
1634 size = (addr_mask_deinterleaved >> 2) + 1;
1571 1635
1572 /* Return size in MBs. */1636 /* Return size in MBs. */
1573 return size >> 10;1637 return size >> 10;
@@ -2232,7 +2296,7 @@ static struct amd64_family_type family_types[] = { · 658 unmodified lines
2232 .f6_id = PCI_DEVICE_ID_AMD_17H_DF_F6,2296 .f6_id = PCI_DEVICE_ID_AMD_17H_DF_F6,
2233 .ops = {2297 .ops = {
2234 .early_channel_count = f17_early_channel_count,2298 .early_channel_count = f17_early_channel_count,
2235 .dbam_to_cs = f17_base_addr_to_cs_size,2299 .dbam_to_cs = f17_addr_mask_to_cs_size,
2236 }2300 }
2237 },2301 },
2238 [F17_M10H_CPUS] = {2302 [F17_M10H_CPUS] = {
@@ -2241,7 +2305,7 @@ static struct amd64_family_type family_types[] = { · 2 unmodified lines
2241 .f6_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F6,2305 .f6_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F6,
2242 .ops = {2306 .ops = {
2243 .early_channel_count = f17_early_channel_count,2307 .early_channel_count = f17_early_channel_count,
2244 .dbam_to_cs = f17_base_addr_to_cs_size,2308 .dbam_to_cs = f17_addr_mask_to_cs_size,
2245 }2309 }
2246 },2310 },
2247 [F17_M30H_CPUS] = {2311 [F17_M30H_CPUS] = {
@@ -2250,7 +2314,16 @@ static struct amd64_family_type family_types[] = { · 2 unmodified lines
2250 .f6_id = PCI_DEVICE_ID_AMD_17H_M30H_DF_F6,2314 .f6_id = PCI_DEVICE_ID_AMD_17H_M30H_DF_F6,
2251 .ops = {2315 .ops = {
2252 .early_channel_count = f17_early_channel_count,2316 .early_channel_count = f17_early_channel_count,
2253 .dbam_to_cs = f17_base_addr_to_cs_size,2317 .dbam_to_cs = f17_addr_mask_to_cs_size,
2318 }
2319 },
2320 [F17_M70H_CPUS] = {
2321 .ctl_name = "F17h_M70h",
2322 .f0_id = PCI_DEVICE_ID_AMD_17H_M70H_DF_F0,
2323 .f6_id = PCI_DEVICE_ID_AMD_17H_M70H_DF_F6,
2324 .ops = {
2325 .early_channel_count = f17_early_channel_count,
2326 .dbam_to_cs = f17_addr_mask_to_cs_size,
2254 }2327 }
2255 },2328 },
2256};2329};
@@ -2537,13 +2610,6 @@ static void decode_umc_error(int node_id, struct mce *m) · 280 unmodified lines
2537 2610
2538 err.channel = find_umc_channel(m);2611 err.channel = find_umc_channel(m);
2539 2612
2540 if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
2541 err.err_code = ERR_NORM_ADDR;
2542 goto log_error;
2543 }
2544
2545 error_address_to_page_and_offset(sys_addr, &err);
2546
2547 if (!(m->status & MCI_STATUS_SYNDV)) {2613 if (!(m->status & MCI_STATUS_SYNDV)) {
2548 err.err_code = ERR_SYND;2614 err.err_code = ERR_SYND;
2549 goto log_error;2615 goto log_error;
@@ -2560,6 +2626,13 @@ static void decode_umc_error(int node_id, struct mce *m) · 10 unmodified lines
2560 2626
2561 err.csrow = m->synd & 0x7;2627 err.csrow = m->synd & 0x7;
2562 2628
2629 if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
2630 err.err_code = ERR_NORM_ADDR;
2631 goto log_error;
2632 }
2633
2634 error_address_to_page_and_offset(sys_addr, &err);
2635
2563log_error:2636log_error:
2564 __log_ecc_error(mci, &err, ecc_type);2637 __log_ecc_error(mci, &err, ecc_type);
2565}2638}
@@ -2809,10 +2882,12 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig) · 243 unmodified lines
2809 int csrow_nr = csrow_nr_orig;2882 int csrow_nr = csrow_nr_orig;
2810 u32 cs_mode, nr_pages;2883 u32 cs_mode, nr_pages;
2811 2884
2812 if (!pvt->umc)2885 if (!pvt->umc) {
2813 csrow_nr >>= 1;2886 csrow_nr >>= 1;
2814 2887 cs_mode = DBAM_DIMM(csrow_nr, dbam);
2815 cs_mode = DBAM_DIMM(csrow_nr, dbam);2888 } else {
2889 cs_mode = f17_get_cs_mode(csrow_nr >> 1, dct, pvt);
2890 }
2816 2891
2817 nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr);2892 nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr);
2818 nr_pages <<= 20 - PAGE_SHIFT;2893 nr_pages <<= 20 - PAGE_SHIFT;
@@ -2824,6 +2899,49 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig) · 5 unmodified lines
2824 return nr_pages;2899 return nr_pages;
2825}2900}
2826 2901
2902static int init_csrows_df(struct mem_ctl_info *mci)
2903{
2904 struct amd64_pvt *pvt = mci->pvt_info;
2905 enum edac_type edac_mode = EDAC_NONE;
2906 enum dev_type dev_type = DEV_UNKNOWN;
2907 struct dimm_info *dimm;
2908 int empty = 1;
2909 u8 umc, cs;
2910
2911 if (mci->edac_ctl_cap & EDAC_FLAG_S16ECD16ED) {
2912 edac_mode = EDAC_S16ECD16ED;
2913 dev_type = DEV_X16;
2914 } else if (mci->edac_ctl_cap & EDAC_FLAG_S8ECD8ED) {
2915 edac_mode = EDAC_S8ECD8ED;
2916 dev_type = DEV_X8;
2917 } else if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED) {
2918 edac_mode = EDAC_S4ECD4ED;
2919 dev_type = DEV_X4;
2920 } else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED) {
2921 edac_mode = EDAC_SECDED;
2922 }
2923
2924 for_each_umc(umc) {
2925 for_each_chip_select(cs, umc, pvt) {
2926 if (!csrow_enabled(cs, umc, pvt))
2927 continue;
2928
2929 empty = 0;
2930 dimm = mci->csrows[cs]->channels[umc]->dimm;
2931
2932 edac_dbg(1, "MC node: %d, csrow: %d\n",
2933 pvt->mc_node_id, cs);
2934
2935 dimm->nr_pages = get_csrow_nr_pages(pvt, umc, cs);
2936 dimm->mtype = pvt->dram_type;
2937 dimm->edac_mode = edac_mode;
2938 dimm->dtype = dev_type;
2939 }
2940 }
2941
2942 return empty;
2943}
2944
2827/*2945/*
2828 * Initialize the array of csrow attribute instances, based on the values2946 * Initialize the array of csrow attribute instances, based on the values
2829 * from pci config hardware registers.2947 * from pci config hardware registers.
@@ -2838,15 +2956,16 @@ static int init_csrows(struct mem_ctl_info *mci) · 8 unmodified lines
2838 int nr_pages = 0;2956 int nr_pages = 0;
2839 u32 val;2957 u32 val;
2840 2958
2841 if (!pvt->umc) {2959 if (pvt->umc)
2842 amd64_read_pci_cfg(pvt->F3, NBCFG, &val);2960 return init_csrows_df(mci);
2843 2961
2844 pvt->nbcfg = val;2962 amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
2845 2963
2846 edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",2964 pvt->nbcfg = val;
2847 pvt->mc_node_id, val,2965
2848 !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));2966 edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
2849 }2967 pvt->mc_node_id, val,
2968 !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
2850 2969
2851 /*2970 /*
2852 * We iterate over DCT0 here but we look at DCT1 in parallel, if needed.2971 * We iterate over DCT0 here but we look at DCT1 in parallel, if needed.
@@ -2883,13 +3002,7 @@ static int init_csrows(struct mem_ctl_info *mci) · 30 unmodified lines
2883 edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);3002 edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
2884 3003
2885 /* Determine DIMM ECC mode: */3004 /* Determine DIMM ECC mode: */
2886 if (pvt->umc) {3005 if (pvt->nbcfg & NBCFG_ECC_ENABLE) {
2887 if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED)
2888 edac_mode = EDAC_S4ECD4ED;
2889 else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED)
2890 edac_mode = EDAC_SECDED;
2891
2892 } else if (pvt->nbcfg & NBCFG_ECC_ENABLE) {
2893 edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL)3006 edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL)
2894 ? EDAC_S4ECD4ED3007 ? EDAC_S4ECD4ED
2895 : EDAC_SECDED;3008 : EDAC_SECDED;
@@ -3137,12 +3250,15 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid) · 241 unmodified lines
3137static inline void3250static inline void
3138f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt)3251f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt)
3139{3252{
3140 u8 i, ecc_en = 1, cpk_en = 1;3253 u8 i, ecc_en = 1, cpk_en = 1, dev_x4 = 1, dev_x16 = 1;
3141 3254
3142 for_each_umc(i) {3255 for_each_umc(i) {
3143 if (pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) {3256 if (pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) {
3144 ecc_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_ENABLED);3257 ecc_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_ENABLED);
3145 cpk_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_CHIPKILL_CAP);3258 cpk_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_CHIPKILL_CAP);
3259
3260 dev_x4 &= !!(pvt->umc[i].dimm_cfg & BIT(6));
3261 dev_x16 &= !!(pvt->umc[i].dimm_cfg & BIT(7));
3146 }3262 }
3147 }3263 }
3148 3264
@@ -3150,8 +3266,15 @@ f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt) · 1 unmodified line
3150 if (ecc_en) {3266 if (ecc_en) {
3151 mci->edac_ctl_cap |= EDAC_FLAG_SECDED;3267 mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
3152 3268
3153 if (cpk_en)3269 if (!cpk_en)
3270 return;
3271
3272 if (dev_x4)
3154 mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;3273 mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
3274 else if (dev_x16)
3275 mci->edac_ctl_cap |= EDAC_FLAG_S16ECD16ED;
3276 else
3277 mci->edac_ctl_cap |= EDAC_FLAG_S8ECD8ED;
3155 }3278 }
3156}3279}
3157 3280
@@ -3241,6 +3364,10 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt) · 83 unmodified lines
3241 fam_type = &family_types[F17_M30H_CPUS];3364 fam_type = &family_types[F17_M30H_CPUS];
3242 pvt->ops = &family_types[F17_M30H_CPUS].ops;3365 pvt->ops = &family_types[F17_M30H_CPUS].ops;
3243 break;3366 break;
3367 } else if (pvt->model >= 0x70 && pvt->model <= 0x7f) {
3368 fam_type = &family_types[F17_M70H_CPUS];
3369 pvt->ops = &family_types[F17_M70H_CPUS].ops;
3370 break;
3244 }3371 }
3245 /* fall through */3372 /* fall through */
3246 case 0x18:3373 case 0x18:
drivers/edac/amd64_edac.h+12−3
@@ -96,6 +96,7 @@ · 95 unmodified lines
96/* Hardware limit on ChipSelect rows per MC and processors per system */96/* Hardware limit on ChipSelect rows per MC and processors per system */
97#define NUM_CHIPSELECTS 897#define NUM_CHIPSELECTS 8
98#define DRAM_RANGES 898#define DRAM_RANGES 8
99#define NUM_CONTROLLERS 8
99 100
100#define ON true101#define ON true
101#define OFF false102#define OFF false
@@ -119,6 +120,8 @@ · 17 unmodified lines
119#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F6 0x15ee120#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F6 0x15ee
120#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F0 0x1490121#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F0 0x1490
121#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F6 0x1496122#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F6 0x1496
123#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F0 0x1440
124#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F6 0x1446
122 125
123/*126/*
124 * Function 1 - Address Map127 * Function 1 - Address Map
@@ -168,7 +171,8 @@ · 43 unmodified lines
168#define DCSM0 0x60171#define DCSM0 0x60
169#define DCSM1 0x160172#define DCSM1 0x160
170 173
171#define csrow_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)174#define csrow_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)
175#define csrow_sec_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases_sec[(i)] & DCSB_CS_ENABLE)
172 176
173#define DRAM_CONTROL 0x78177#define DRAM_CONTROL 0x78
174 178
@@ -258,7 +262,9 @@ · 83 unmodified lines
258 262
259/* UMC CH register offsets */263/* UMC CH register offsets */
260#define UMCCH_BASE_ADDR 0x0264#define UMCCH_BASE_ADDR 0x0
265#define UMCCH_BASE_ADDR_SEC 0x10
261#define UMCCH_ADDR_MASK 0x20266#define UMCCH_ADDR_MASK 0x20
267#define UMCCH_ADDR_MASK_SEC 0x28
262#define UMCCH_ADDR_CFG 0x30268#define UMCCH_ADDR_CFG 0x30
263#define UMCCH_DIMM_CFG 0x80269#define UMCCH_DIMM_CFG 0x80
264#define UMCCH_UMC_CFG 0x100270#define UMCCH_UMC_CFG 0x100
@@ -285,6 +291,7 @@ enum amd_families { · 20 unmodified lines
285 F17_CPUS,291 F17_CPUS,
286 F17_M10H_CPUS,292 F17_M10H_CPUS,
287 F17_M30H_CPUS,293 F17_M30H_CPUS,
294 F17_M70H_CPUS,
288 NUM_FAMILIES,295 NUM_FAMILIES,
289};296};
290 297
@@ -311,9 +318,11 @@ struct dram_range { · 20 unmodified lines
311/* A DCT chip selects collection */318/* A DCT chip selects collection */
312struct chip_select {319struct chip_select {
313 u32 csbases[NUM_CHIPSELECTS];320 u32 csbases[NUM_CHIPSELECTS];
321 u32 csbases_sec[NUM_CHIPSELECTS];
314 u8 b_cnt;322 u8 b_cnt;
315 323
316 u32 csmasks[NUM_CHIPSELECTS];324 u32 csmasks[NUM_CHIPSELECTS];
325 u32 csmasks_sec[NUM_CHIPSELECTS];
317 u8 m_cnt;326 u8 m_cnt;
318};327};
319 328
@@ -351,8 +360,8 @@ struct amd64_pvt { · 31 unmodified lines
351 u32 dbam0; /* DRAM Base Address Mapping reg for DCT0 */360 u32 dbam0; /* DRAM Base Address Mapping reg for DCT0 */
352 u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */361 u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */
353 362
354 /* one for each DCT */363 /* one for each DCT/UMC */
355 struct chip_select csels[2];364 struct chip_select csels[NUM_CONTROLLERS];
356 365
357 /* DRAM base and limit pairs F1x[78,70,68,60,58,50,48,40] */366 /* DRAM base and limit pairs F1x[78,70,68,60,58,50,48,40] */
358 struct dram_range ranges[DRAM_RANGES];367 struct dram_range ranges[DRAM_RANGES];
drivers/edac/bluefield_edac.c+356−0
@@ -0,0 +1,356 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Bluefield-specific EDAC driver.
4 *
5 * Copyright (c) 2019 Mellanox Technologies.
6 */
7
8#include <linux/acpi.h>
9#include <linux/arm-smccc.h>
10#include <linux/bitfield.h>
11#include <linux/edac.h>
12#include <linux/io.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15
16#include "edac_module.h"
17
18#define DRIVER_NAME "bluefield-edac"
19
20/*
21 * Mellanox BlueField EMI (External Memory Interface) register definitions.
22 */
23
24#define MLXBF_ECC_CNT 0x340
25#define MLXBF_ECC_CNT__SERR_CNT GENMASK(15, 0)
26#define MLXBF_ECC_CNT__DERR_CNT GENMASK(31, 16)
27
28#define MLXBF_ECC_ERR 0x348
29#define MLXBF_ECC_ERR__SECC BIT(0)
30#define MLXBF_ECC_ERR__DECC BIT(16)
31
32#define MLXBF_ECC_LATCH_SEL 0x354
33#define MLXBF_ECC_LATCH_SEL__START BIT(24)
34
35#define MLXBF_ERR_ADDR_0 0x358
36
37#define MLXBF_ERR_ADDR_1 0x37c
38
39#define MLXBF_SYNDROM 0x35c
40#define MLXBF_SYNDROM__DERR BIT(0)
41#define MLXBF_SYNDROM__SERR BIT(1)
42#define MLXBF_SYNDROM__SYN GENMASK(25, 16)
43
44#define MLXBF_ADD_INFO 0x364
45#define MLXBF_ADD_INFO__ERR_PRANK GENMASK(9, 8)
46
47#define MLXBF_EDAC_MAX_DIMM_PER_MC 2
48#define MLXBF_EDAC_ERROR_GRAIN 8
49
50/*
51 * Request MLNX_SIP_GET_DIMM_INFO
52 *
53 * Retrieve information about DIMM on a certain slot.
54 *
55 * Call register usage:
56 * a0: MLNX_SIP_GET_DIMM_INFO
57 * a1: (Memory controller index) << 16 | (Dimm index in memory controller)
58 * a2-7: not used.
59 *
60 * Return status:
61 * a0: MLXBF_DIMM_INFO defined below describing the DIMM.
62 * a1-3: not used.
63 */
64#define MLNX_SIP_GET_DIMM_INFO 0x82000008
65
66/* Format for the SMC response about the memory information */
67#define MLXBF_DIMM_INFO__SIZE_GB GENMASK_ULL(15, 0)
68#define MLXBF_DIMM_INFO__IS_RDIMM BIT(16)
69#define MLXBF_DIMM_INFO__IS_LRDIMM BIT(17)
70#define MLXBF_DIMM_INFO__IS_NVDIMM BIT(18)
71#define MLXBF_DIMM_INFO__RANKS GENMASK_ULL(23, 21)
72#define MLXBF_DIMM_INFO__PACKAGE_X GENMASK_ULL(31, 24)
73
74struct bluefield_edac_priv {
75 int dimm_ranks[MLXBF_EDAC_MAX_DIMM_PER_MC];
76 void __iomem *emi_base;
77 int dimm_per_mc;
78};
79
80static u64 smc_call1(u64 smc_op, u64 smc_arg)
81{
82 struct arm_smccc_res res;
83
84 arm_smccc_smc(smc_op, smc_arg, 0, 0, 0, 0, 0, 0, &res);
85
86 return res.a0;
87}
88
89/*
90 * Gather the ECC information from the External Memory Interface registers
91 * and report it to the edac handler.
92 */
93static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
94 int error_cnt,
95 int is_single_ecc)
96{
97 struct bluefield_edac_priv *priv = mci->pvt_info;
98 u32 dram_additional_info, err_prank, edea0, edea1;
99 u32 ecc_latch_select, dram_syndrom, serr, derr, syndrom;
100 enum hw_event_mc_err_type ecc_type;
101 u64 ecc_dimm_addr;
102 int ecc_dimm;
103
104 ecc_type = is_single_ecc ? HW_EVENT_ERR_CORRECTED :
105 HW_EVENT_ERR_UNCORRECTED;
106
107 /*
108 * Tell the External Memory Interface to populate the relevant
109 * registers with information about the last ECC error occurrence.
110 */
111 ecc_latch_select = MLXBF_ECC_LATCH_SEL__START;
112 writel(ecc_latch_select, priv->emi_base + MLXBF_ECC_LATCH_SEL);
113
114 /*
115 * Verify that the ECC reported info in the registers is of the
116 * same type as the one asked to report. If not, just report the
117 * error without the detailed information.
118 */
119 dram_syndrom = readl(priv->emi_base + MLXBF_SYNDROM);
120 serr = FIELD_GET(MLXBF_SYNDROM__SERR, dram_syndrom);
121 derr = FIELD_GET(MLXBF_SYNDROM__DERR, dram_syndrom);
122 syndrom = FIELD_GET(MLXBF_SYNDROM__SYN, dram_syndrom);
123
124 if ((is_single_ecc && !serr) || (!is_single_ecc && !derr)) {
125 edac_mc_handle_error(ecc_type, mci, error_cnt, 0, 0, 0,
126 0, 0, -1, mci->ctl_name, "");
127 return;
128 }
129
130 dram_additional_info = readl(priv->emi_base + MLXBF_ADD_INFO);
131 err_prank = FIELD_GET(MLXBF_ADD_INFO__ERR_PRANK, dram_additional_info);
132
133 ecc_dimm = (err_prank >= 2 && priv->dimm_ranks[0] <= 2) ? 1 : 0;
134
135 edea0 = readl(priv->emi_base + MLXBF_ERR_ADDR_0);
136 edea1 = readl(priv->emi_base + MLXBF_ERR_ADDR_1);
137
138 ecc_dimm_addr = ((u64)edea1 << 32) | edea0;
139
140 edac_mc_handle_error(ecc_type, mci, error_cnt,
141 PFN_DOWN(ecc_dimm_addr),
142 offset_in_page(ecc_dimm_addr),
143 syndrom, ecc_dimm, 0, 0, mci->ctl_name, "");
144}
145
146static void bluefield_edac_check(struct mem_ctl_info *mci)
147{
148 struct bluefield_edac_priv *priv = mci->pvt_info;
149 u32 ecc_count, single_error_count, double_error_count, ecc_error = 0;
150
151 /*
152 * The memory controller might not be initialized by the firmware
153 * when there isn't memory, which may lead to bad register readings.
154 */
155 if (mci->edac_cap == EDAC_FLAG_NONE)
156 return;
157
158 ecc_count = readl(priv->emi_base + MLXBF_ECC_CNT);
159 single_error_count = FIELD_GET(MLXBF_ECC_CNT__SERR_CNT, ecc_count);
160 double_error_count = FIELD_GET(MLXBF_ECC_CNT__DERR_CNT, ecc_count);
161
162 if (single_error_count) {
163 ecc_error |= MLXBF_ECC_ERR__SECC;
164
165 bluefield_gather_report_ecc(mci, single_error_count, 1);
166 }
167
168 if (double_error_count) {
169 ecc_error |= MLXBF_ECC_ERR__DECC;
170
171 bluefield_gather_report_ecc(mci, double_error_count, 0);
172 }
173
174 /* Write to clear reported errors. */
175 if (ecc_count)
176 writel(ecc_error, priv->emi_base + MLXBF_ECC_ERR);
177}
178
179/* Initialize the DIMMs information for the given memory controller. */
180static void bluefield_edac_init_dimms(struct mem_ctl_info *mci)
181{
182 struct bluefield_edac_priv *priv = mci->pvt_info;
183 int mem_ctrl_idx = mci->mc_idx;
184 struct dimm_info *dimm;
185 u64 smc_info, smc_arg;
186 int is_empty = 1, i;
187
188 for (i = 0; i < priv->dimm_per_mc; i++) {
189 dimm = mci->dimms[i];
190
191 smc_arg = mem_ctrl_idx << 16 | i;
192 smc_info = smc_call1(MLNX_SIP_GET_DIMM_INFO, smc_arg);
193
194 if (!FIELD_GET(MLXBF_DIMM_INFO__SIZE_GB, smc_info)) {
195 dimm->mtype = MEM_EMPTY;
196 continue;
197 }
198
199 is_empty = 0;
200
201 dimm->edac_mode = EDAC_SECDED;
202
203 if (FIELD_GET(MLXBF_DIMM_INFO__IS_NVDIMM, smc_info))
204 dimm->mtype = MEM_NVDIMM;
205 else if (FIELD_GET(MLXBF_DIMM_INFO__IS_LRDIMM, smc_info))
206 dimm->mtype = MEM_LRDDR4;
207 else if (FIELD_GET(MLXBF_DIMM_INFO__IS_RDIMM, smc_info))
208 dimm->mtype = MEM_RDDR4;
209 else
210 dimm->mtype = MEM_DDR4;
211
212 dimm->nr_pages =
213 FIELD_GET(MLXBF_DIMM_INFO__SIZE_GB, smc_info) *
214 (SZ_1G / PAGE_SIZE);
215 dimm->grain = MLXBF_EDAC_ERROR_GRAIN;
216
217 /* Mem controller for BlueField only supports x4, x8 and x16 */
218 switch (FIELD_GET(MLXBF_DIMM_INFO__PACKAGE_X, smc_info)) {
219 case 4:
220 dimm->dtype = DEV_X4;
221 break;
222 case 8:
223 dimm->dtype = DEV_X8;
224 break;
225 case 16:
226 dimm->dtype = DEV_X16;
227 break;
228 default:
229 dimm->dtype = DEV_UNKNOWN;
230 }
231
232 priv->dimm_ranks[i] =
233 FIELD_GET(MLXBF_DIMM_INFO__RANKS, smc_info);
234 }
235
236 if (is_empty)
237 mci->edac_cap = EDAC_FLAG_NONE;
238 else
239 mci->edac_cap = EDAC_FLAG_SECDED;
240}
241
242static int bluefield_edac_mc_probe(struct platform_device *pdev)
243{
244 struct bluefield_edac_priv *priv;
245 struct device *dev = &pdev->dev;
246 struct edac_mc_layer layers[1];
247 struct mem_ctl_info *mci;
248 struct resource *emi_res;
249 unsigned int mc_idx, dimm_count;
250 int rc, ret;
251
252 /* Read the MSS (Memory SubSystem) index from ACPI table. */
253 if (device_property_read_u32(dev, "mss_number", &mc_idx)) {
254 dev_warn(dev, "bf_edac: MSS number unknown\n");
255 return -EINVAL;
256 }
257
258 /* Read the DIMMs per MC from ACPI table. */
259 if (device_property_read_u32(dev, "dimm_per_mc", &dimm_count)) {
260 dev_warn(dev, "bf_edac: DIMMs per MC unknown\n");
261 return -EINVAL;
262 }
263
264 if (dimm_count > MLXBF_EDAC_MAX_DIMM_PER_MC) {
265 dev_warn(dev, "bf_edac: DIMMs per MC not valid\n");
266 return -EINVAL;
267 }
268
269 emi_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
270 if (!emi_res)
271 return -EINVAL;
272
273 layers[0].type = EDAC_MC_LAYER_SLOT;
274 layers[0].size = dimm_count;
275 layers[0].is_virt_csrow = true;
276
277 mci = edac_mc_alloc(mc_idx, ARRAY_SIZE(layers), layers, sizeof(*priv));
278 if (!mci)
279 return -ENOMEM;
280
281 priv = mci->pvt_info;
282
283 priv->dimm_per_mc = dimm_count;
284 priv->emi_base = devm_ioremap_resource(dev, emi_res);
285 if (IS_ERR(priv->emi_base)) {
286 dev_err(dev, "failed to map EMI IO resource\n");
287 ret = PTR_ERR(priv->emi_base);
288 goto err;
289 }
290
291 mci->pdev = dev;
292 mci->mtype_cap = MEM_FLAG_DDR4 | MEM_FLAG_RDDR4 |
293 MEM_FLAG_LRDDR4 | MEM_FLAG_NVDIMM;
294 mci->edac_ctl_cap = EDAC_FLAG_SECDED;
295
296 mci->mod_name = DRIVER_NAME;
297 mci->ctl_name = "BlueField_Memory_Controller";
298 mci->dev_name = dev_name(dev);
299 mci->edac_check = bluefield_edac_check;
300
301 /* Initialize mci with the actual populated DIMM information. */
302 bluefield_edac_init_dimms(mci);
303
304 platform_set_drvdata(pdev, mci);
305
306 /* Register with EDAC core */
307 rc = edac_mc_add_mc(mci);
308 if (rc) {
309 dev_err(dev, "failed to register with EDAC core\n");
310 ret = rc;
311 goto err;
312 }
313
314 /* Only POLL mode supported so far. */
315 edac_op_state = EDAC_OPSTATE_POLL;
316
317 return 0;
318
319err:
320 edac_mc_free(mci);
321
322 return ret;
323
324}
325
326static int bluefield_edac_mc_remove(struct platform_device *pdev)
327{
328 struct mem_ctl_info *mci = platform_get_drvdata(pdev);
329
330 edac_mc_del_mc(&pdev->dev);
331 edac_mc_free(mci);
332
333 return 0;
334}
335
336static const struct acpi_device_id bluefield_mc_acpi_ids[] = {
337 {"MLNXBF08", 0},
338 {}
339};
340
341MODULE_DEVICE_TABLE(acpi, bluefield_mc_acpi_ids);
342
343static struct platform_driver bluefield_edac_mc_driver = {
344 .driver = {
345 .name = DRIVER_NAME,
346 .acpi_match_table = bluefield_mc_acpi_ids,
347 },
348 .probe = bluefield_edac_mc_probe,
349 .remove = bluefield_edac_mc_remove,
350};
351
352module_platform_driver(bluefield_edac_mc_driver);
353
354MODULE_DESCRIPTION("Mellanox BlueField memory edac driver");
355MODULE_AUTHOR("Mellanox Technologies");
356MODULE_LICENSE("GPL v2");
drivers/edac/edac_mc.c+28−25
@@ -114,8 +114,8 @@ static const struct kernel_param_ops edac_report_ops = { · 113 unmodified lines
114 114
115module_param_cb(edac_report, &edac_report_ops, &edac_report, 0644);115module_param_cb(edac_report, &edac_report_ops, &edac_report, 0644);
116 116
117unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf,117unsigned int edac_dimm_info_location(struct dimm_info *dimm, char *buf,
118 unsigned len)118 unsigned int len)
119{119{
120 struct mem_ctl_info *mci = dimm->mci;120 struct mem_ctl_info *mci = dimm->mci;
121 int i, n, count = 0;121 int i, n, count = 0;
@@ -236,9 +236,9 @@ EXPORT_SYMBOL_GPL(edac_mem_types); · 114 unmodified lines
236 * At return, the pointer 'p' will be incremented to be used on a next call236 * At return, the pointer 'p' will be incremented to be used on a next call
237 * to this function.237 * to this function.
238 */238 */
239void *edac_align_ptr(void **p, unsigned size, int n_elems)239void *edac_align_ptr(void **p, unsigned int size, int n_elems)
240{240{
241 unsigned align, r;241 unsigned int align, r;
242 void *ptr = *p;242 void *ptr = *p;
243 243
244 *p += size * n_elems;244 *p += size * n_elems;
@@ -275,38 +275,37 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems) · 30 unmodified lines
275 275
276static void _edac_mc_free(struct mem_ctl_info *mci)276static void _edac_mc_free(struct mem_ctl_info *mci)
277{277{
278 int i, chn, row;
279 struct csrow_info *csr;278 struct csrow_info *csr;
280 const unsigned int tot_dimms = mci->tot_dimms;279 int i, chn, row;
281 const unsigned int tot_channels = mci->num_cschannel;
282 const unsigned int tot_csrows = mci->nr_csrows;
283 280
284 if (mci->dimms) {281 if (mci->dimms) {
285 for (i = 0; i < tot_dimms; i++)282 for (i = 0; i < mci->tot_dimms; i++)
286 kfree(mci->dimms[i]);283 kfree(mci->dimms[i]);
287 kfree(mci->dimms);284 kfree(mci->dimms);
288 }285 }
286
289 if (mci->csrows) {287 if (mci->csrows) {
290 for (row = 0; row < tot_csrows; row++) {288 for (row = 0; row < mci->nr_csrows; row++) {
291 csr = mci->csrows[row];289 csr = mci->csrows[row];
292 if (csr) {290 if (!csr)
293 if (csr->channels) {291 continue;
294 for (chn = 0; chn < tot_channels; chn++)292
295 kfree(csr->channels[chn]);293 if (csr->channels) {
296 kfree(csr->channels);294 for (chn = 0; chn < mci->num_cschannel; chn++)
297 }295 kfree(csr->channels[chn]);
298 kfree(csr);296 kfree(csr->channels);
299 }297 }
298 kfree(csr);
300 }299 }
301 kfree(mci->csrows);300 kfree(mci->csrows);
302 }301 }
303 kfree(mci);302 kfree(mci);
304}303}
305 304
306struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,305struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
307 unsigned n_layers,306 unsigned int n_layers,
308 struct edac_mc_layer *layers,307 struct edac_mc_layer *layers,
309 unsigned sz_pvt)308 unsigned int sz_pvt)
310{309{
311 struct mem_ctl_info *mci;310 struct mem_ctl_info *mci;
312 struct edac_mc_layer *layer;311 struct edac_mc_layer *layer;
@@ -314,9 +313,9 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, · 1 unmodified line
314 struct rank_info *chan;313 struct rank_info *chan;
315 struct dimm_info *dimm;314 struct dimm_info *dimm;
316 u32 *ce_per_layer[EDAC_MAX_LAYERS], *ue_per_layer[EDAC_MAX_LAYERS];315 u32 *ce_per_layer[EDAC_MAX_LAYERS], *ue_per_layer[EDAC_MAX_LAYERS];
317 unsigned pos[EDAC_MAX_LAYERS];316 unsigned int pos[EDAC_MAX_LAYERS];
318 unsigned size, tot_dimms = 1, count = 1;317 unsigned int size, tot_dimms = 1, count = 1;
319 unsigned tot_csrows = 1, tot_channels = 1, tot_errcount = 0;318 unsigned int tot_csrows = 1, tot_channels = 1, tot_errcount = 0;
320 void *pvt, *p, *ptr = NULL;319 void *pvt, *p, *ptr = NULL;
321 int i, j, row, chn, n, len, off;320 int i, j, row, chn, n, len, off;
322 bool per_rank = false;321 bool per_rank = false;
@@ -1235,9 +1234,13 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, · 912 unmodified lines
1235 if (p > e->location)1234 if (p > e->location)
1236 *(p - 1) = '\0';1235 *(p - 1) = '\0';
1237 1236
1238 /* Report the error via the trace interface */1237 /* Sanity-check driver-supplied grain value. */
1239 grain_bits = fls_long(e->grain) + 1;1238 if (WARN_ON_ONCE(!e->grain))
1239 e->grain = 1;
1240 1240
1241 grain_bits = fls_long(e->grain - 1);
1242
1243 /* Report the error via the trace interface */
1241 if (IS_ENABLED(CONFIG_RAS))1244 if (IS_ENABLED(CONFIG_RAS))
1242 trace_mc_event(type, e->msg, e->label, e->error_count,1245 trace_mc_event(type, e->msg, e->label, e->error_count,
1243 mci->mc_idx, e->top_layer, e->mid_layer,1246 mci->mc_idx, e->top_layer, e->mid_layer,
drivers/edac/edac_mc.h+3−3
@@ -122,10 +122,10 @@ do { \ · 121 unmodified lines
122 * On success, return a pointer to struct mem_ctl_info pointer;122 * On success, return a pointer to struct mem_ctl_info pointer;
123 * %NULL otherwise123 * %NULL otherwise
124 */124 */
125struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,125struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
126 unsigned n_layers,126 unsigned int n_layers,
127 struct edac_mc_layer *layers,127 struct edac_mc_layer *layers,
128 unsigned sz_pvt);128 unsigned int sz_pvt);
129 129
130/**130/**
131 * edac_get_owner - Return the owner's mod_name of EDAC MC131 * edac_get_owner - Return the owner's mod_name of EDAC MC
drivers/edac/edac_mc_sysfs.c+41−51
@@ -131,7 +131,7 @@ static const char * const edac_caps[] = { · 130 unmodified lines
131 131
132struct dev_ch_attribute {132struct dev_ch_attribute {
133 struct device_attribute attr;133 struct device_attribute attr;
134 int channel;134 unsigned int channel;
135};135};
136 136
137#define DEVICE_CHANNEL(_name, _mode, _show, _store, _var) \137#define DEVICE_CHANNEL(_name, _mode, _show, _store, _var) \
@@ -200,7 +200,7 @@ static ssize_t channel_dimm_label_show(struct device *dev, · 62 unmodified lines
200 char *data)200 char *data)
201{201{
202 struct csrow_info *csrow = to_csrow(dev);202 struct csrow_info *csrow = to_csrow(dev);
203 unsigned chan = to_channel(mattr);203 unsigned int chan = to_channel(mattr);
204 struct rank_info *rank = csrow->channels[chan];204 struct rank_info *rank = csrow->channels[chan];
205 205
206 /* if field has not been initialized, there is nothing to send */206 /* if field has not been initialized, there is nothing to send */
@@ -216,7 +216,7 @@ static ssize_t channel_dimm_label_store(struct device *dev, · 9 unmodified lines
216 const char *data, size_t count)216 const char *data, size_t count)
217{217{
218 struct csrow_info *csrow = to_csrow(dev);218 struct csrow_info *csrow = to_csrow(dev);
219 unsigned chan = to_channel(mattr);219 unsigned int chan = to_channel(mattr);
220 struct rank_info *rank = csrow->channels[chan];220 struct rank_info *rank = csrow->channels[chan];
221 size_t copy_count = count;221 size_t copy_count = count;
222 222
@@ -240,7 +240,7 @@ static ssize_t channel_ce_count_show(struct device *dev, · 17 unmodified lines
240 struct device_attribute *mattr, char *data)240 struct device_attribute *mattr, char *data)
241{241{
242 struct csrow_info *csrow = to_csrow(dev);242 struct csrow_info *csrow = to_csrow(dev);
243 unsigned chan = to_channel(mattr);243 unsigned int chan = to_channel(mattr);
244 struct rank_info *rank = csrow->channels[chan];244 struct rank_info *rank = csrow->channels[chan];
245 245
246 return sprintf(data, "%u\n", rank->ce_count);246 return sprintf(data, "%u\n", rank->ce_count);
@@ -278,7 +278,7 @@ static void csrow_attr_release(struct device *dev) · 31 unmodified lines
278{278{
279 struct csrow_info *csrow = container_of(dev, struct csrow_info, dev);279 struct csrow_info *csrow = container_of(dev, struct csrow_info, dev);
280 280
281 edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev));281 edac_dbg(1, "device %s released\n", dev_name(dev));
282 kfree(csrow);282 kfree(csrow);
283}283}
284 284
@@ -414,14 +414,16 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci, · 129 unmodified lines
414 dev_set_name(&csrow->dev, "csrow%d", index);414 dev_set_name(&csrow->dev, "csrow%d", index);
415 dev_set_drvdata(&csrow->dev, csrow);415 dev_set_drvdata(&csrow->dev, csrow);
416 416
417 edac_dbg(0, "creating (virtual) csrow node %s\n",
418 dev_name(&csrow->dev));
419
420 err = device_add(&csrow->dev);417 err = device_add(&csrow->dev);
421 if (err)418 if (err) {
419 edac_dbg(1, "failure: create device %s\n", dev_name(&csrow->dev));
422 put_device(&csrow->dev);420 put_device(&csrow->dev);
421 return err;
422 }
423 423
424 return err;424 edac_dbg(0, "device %s created\n", dev_name(&csrow->dev));
425
426 return 0;
425}427}
426 428
427/* Create a CSROW object under specifed edac_mc_device */429/* Create a CSROW object under specifed edac_mc_device */
@@ -435,12 +437,8 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci) · 7 unmodified lines
435 if (!nr_pages_per_csrow(csrow))437 if (!nr_pages_per_csrow(csrow))
436 continue;438 continue;
437 err = edac_create_csrow_object(mci, mci->csrows[i], i);439 err = edac_create_csrow_object(mci, mci->csrows[i], i);
438 if (err < 0) {440 if (err < 0)
439 edac_dbg(1,
440 "failure: create csrow objects for csrow %d\n",
441 i);
442 goto error;441 goto error;
443 }
444 }442 }
445 return 0;443 return 0;
446 444
@@ -624,7 +622,7 @@ static void dimm_attr_release(struct device *dev) · 177 unmodified lines
624{622{
625 struct dimm_info *dimm = container_of(dev, struct dimm_info, dev);623 struct dimm_info *dimm = container_of(dev, struct dimm_info, dev);
626 624
627 edac_dbg(1, "Releasing dimm device %s\n", dev_name(dev));625 edac_dbg(1, "device %s released\n", dev_name(dev));
628 kfree(dimm);626 kfree(dimm);
629}627}
630 628
@@ -653,12 +651,21 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci, · 22 unmodified lines
653 pm_runtime_forbid(&mci->dev);651 pm_runtime_forbid(&mci->dev);
654 652
655 err = device_add(&dimm->dev);653 err = device_add(&dimm->dev);
656 if (err)654 if (err) {
655 edac_dbg(1, "failure: create device %s\n", dev_name(&dimm->dev));
657 put_device(&dimm->dev);656 put_device(&dimm->dev);
657 return err;
658 }
658 659
659 edac_dbg(0, "created rank/dimm device %s\n", dev_name(&dimm->dev));660 if (IS_ENABLED(CONFIG_EDAC_DEBUG)) {
661 char location[80];
660 662
661 return err;663 edac_dimm_info_location(dimm, location, sizeof(location));
664 edac_dbg(0, "device %s created at location %s\n",
665 dev_name(&dimm->dev), location);
666 }
667
668 return 0;
662}669}
663 670
664/*671/*
@@ -901,7 +908,7 @@ static void mci_attr_release(struct device *dev) · 236 unmodified lines
901{908{
902 struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev);909 struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev);
903 910
904 edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev));911 edac_dbg(1, "device %s released\n", dev_name(dev));
905 kfree(mci);912 kfree(mci);
906}913}
907 914
@@ -933,14 +940,15 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, · 25 unmodified lines
933 dev_set_drvdata(&mci->dev, mci);940 dev_set_drvdata(&mci->dev, mci);
934 pm_runtime_forbid(&mci->dev);941 pm_runtime_forbid(&mci->dev);
935 942
936 edac_dbg(0, "creating device %s\n", dev_name(&mci->dev));
937 err = device_add(&mci->dev);943 err = device_add(&mci->dev);
938 if (err < 0) {944 if (err < 0) {
939 edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev));945 edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev));
940 put_device(&mci->dev);946 put_device(&mci->dev);
941 goto out;947 return err;
942 }948 }
943 949
950 edac_dbg(0, "device %s created\n", dev_name(&mci->dev));
951
944 /*952 /*
945 * Create the dimm/rank devices953 * Create the dimm/rank devices
946 */954 */
@@ -950,22 +958,9 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, · 3 unmodified lines
950 if (!dimm->nr_pages)958 if (!dimm->nr_pages)
951 continue;959 continue;
952 960
953#ifdef CONFIG_EDAC_DEBUG
954 edac_dbg(1, "creating dimm%d, located at ", i);
955 if (edac_debug_level >= 1) {
956 int lay;
957 for (lay = 0; lay < mci->n_layers; lay++)
958 printk(KERN_CONT "%s %d ",
959 edac_layer_name[mci->layers[lay].type],
960 dimm->location[lay]);
961 printk(KERN_CONT "\n");
962 }
963#endif
964 err = edac_create_dimm_object(mci, dimm, i);961 err = edac_create_dimm_object(mci, dimm, i);
965 if (err) {962 if (err)
966 edac_dbg(1, "failure: create dimm %d obj\n", i);
967 goto fail_unregister_dimm;963 goto fail_unregister_dimm;
968 }
969 }964 }
970 965
971#ifdef CONFIG_EDAC_LEGACY_SYSFS966#ifdef CONFIG_EDAC_LEGACY_SYSFS
@@ -987,7 +982,6 @@ fail_unregister_dimm: · 15 unmodified lines
987 }982 }
988 device_unregister(&mci->dev);983 device_unregister(&mci->dev);
989 984
990out:
991 return err;985 return err;
992}986}
993 987
@@ -1011,14 +1005,14 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) · 17 unmodified lines
1011 struct dimm_info *dimm = mci->dimms[i];1005 struct dimm_info *dimm = mci->dimms[i];
1012 if (dimm->nr_pages == 0)1006 if (dimm->nr_pages == 0)
1013 continue;1007 continue;
1014 edac_dbg(0, "removing device %s\n", dev_name(&dimm->dev));1008 edac_dbg(1, "unregistering device %s\n", dev_name(&dimm->dev));
1015 device_unregister(&dimm->dev);1009 device_unregister(&dimm->dev);
1016 }1010 }
1017}1011}
1018 1012
1019void edac_unregister_sysfs(struct mem_ctl_info *mci)1013void edac_unregister_sysfs(struct mem_ctl_info *mci)
1020{1014{
1021 edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));1015 edac_dbg(1, "unregistering device %s\n", dev_name(&mci->dev));
1022 device_unregister(&mci->dev);1016 device_unregister(&mci->dev);
1023}1017}
1024 1018
@@ -1029,7 +1023,7 @@ static void mc_attr_release(struct device *dev) · 4 unmodified lines
1029 * parent device, used to create the /sys/devices/mc sysfs node.1023 * parent device, used to create the /sys/devices/mc sysfs node.
1030 * So, there are no attributes on it.1024 * So, there are no attributes on it.
1031 */1025 */
1032 edac_dbg(1, "Releasing device %s\n", dev_name(dev));1026 edac_dbg(1, "device %s released\n", dev_name(dev));
1033 kfree(dev);1027 kfree(dev);
1034}1028}
1035 1029
@@ -1044,10 +1038,8 @@ int __init edac_mc_sysfs_init(void) · 8 unmodified lines
1044 int err;1038 int err;
1045 1039
1046 mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL);1040 mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL);
1047 if (!mci_pdev) {1041 if (!mci_pdev)
1048 err = -ENOMEM;1042 return -ENOMEM;
1049 goto out;
1050 }
1051 1043
1052 mci_pdev->bus = edac_get_sysfs_subsys();1044 mci_pdev->bus = edac_get_sysfs_subsys();
1053 mci_pdev->type = &mc_attr_type;1045 mci_pdev->type = &mc_attr_type;
@@ -1055,17 +1047,15 @@ int __init edac_mc_sysfs_init(void) · 1 unmodified line
1055 dev_set_name(mci_pdev, "mc");1047 dev_set_name(mci_pdev, "mc");
1056 1048
1057 err = device_add(mci_pdev);1049 err = device_add(mci_pdev);
1058 if (err < 0)1050 if (err < 0) {
1059 goto out_put_device;1051 edac_dbg(1, "failure: create device %s\n", dev_name(mci_pdev));
1052 put_device(mci_pdev);
1053 return err;
1054 }
1060 1055
1061 edac_dbg(0, "device %s created\n", dev_name(mci_pdev));1056 edac_dbg(0, "device %s created\n", dev_name(mci_pdev));
1062 1057
1063 return 0;1058 return 0;
1064
1065 out_put_device:
1066 put_device(mci_pdev);
1067 out:
1068 return err;
1069}1059}
1070 1060
1071void edac_mc_sysfs_exit(void)1061void edac_mc_sysfs_exit(void)
drivers/edac/ghes_edac.c+1−1
@@ -68,7 +68,7 @@ struct memdev_dmi_entry { · 67 unmodified lines
68 68
69struct ghes_edac_dimm_fill {69struct ghes_edac_dimm_fill {
70 struct mem_ctl_info *mci;70 struct mem_ctl_info *mci;
71 unsigned count;71 unsigned int count;
72};72};
73 73
74static void ghes_edac_count_dimms(const struct dmi_header *dh, void *arg)74static void ghes_edac_count_dimms(const struct dmi_header *dh, void *arg)
drivers/edac/i5100_edac.c+9−7
@@ -417,7 +417,8 @@ static const char *i5100_err_msg(unsigned err) · 416 unmodified lines
417}417}
418 418
419/* convert csrow index into a rank (per channel -- 0..5) */419/* convert csrow index into a rank (per channel -- 0..5) */
420static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow)420static unsigned int i5100_csrow_to_rank(const struct mem_ctl_info *mci,
421 unsigned int csrow)
421{422{
422 const struct i5100_priv *priv = mci->pvt_info;423 const struct i5100_priv *priv = mci->pvt_info;
423 424
@@ -425,7 +426,8 @@ static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow) · 1 unmodified line
425}426}
426 427
427/* convert csrow index into a channel (0..1) */428/* convert csrow index into a channel (0..1) */
428static int i5100_csrow_to_chan(const struct mem_ctl_info *mci, int csrow)429static unsigned int i5100_csrow_to_chan(const struct mem_ctl_info *mci,
430 unsigned int csrow)
429{431{
430 const struct i5100_priv *priv = mci->pvt_info;432 const struct i5100_priv *priv = mci->pvt_info;
431 433
@@ -653,11 +655,11 @@ static struct pci_dev *pci_get_device_func(unsigned vendor, · 221 unmodified lines
653 return ret;655 return ret;
654}656}
655 657
656static unsigned long i5100_npages(struct mem_ctl_info *mci, int csrow)658static unsigned long i5100_npages(struct mem_ctl_info *mci, unsigned int csrow)
657{659{
658 struct i5100_priv *priv = mci->pvt_info;660 struct i5100_priv *priv = mci->pvt_info;
659 const unsigned chan_rank = i5100_csrow_to_rank(mci, csrow);661 const unsigned int chan_rank = i5100_csrow_to_rank(mci, csrow);
660 const unsigned chan = i5100_csrow_to_chan(mci, csrow);662 const unsigned int chan = i5100_csrow_to_chan(mci, csrow);
661 unsigned addr_lines;663 unsigned addr_lines;
662 664
663 /* dimm present? */665 /* dimm present? */
@@ -852,8 +854,8 @@ static void i5100_init_csrows(struct mem_ctl_info *mci) · 188 unmodified lines
852 for (i = 0; i < mci->tot_dimms; i++) {854 for (i = 0; i < mci->tot_dimms; i++) {
853 struct dimm_info *dimm;855 struct dimm_info *dimm;
854 const unsigned long npages = i5100_npages(mci, i);856 const unsigned long npages = i5100_npages(mci, i);
855 const unsigned chan = i5100_csrow_to_chan(mci, i);857 const unsigned int chan = i5100_csrow_to_chan(mci, i);
856 const unsigned rank = i5100_csrow_to_rank(mci, i);858 const unsigned int rank = i5100_csrow_to_rank(mci, i);
857 859
858 if (!npages)860 if (!npages)
859 continue;861 continue;
drivers/edac/pnd2_edac.c+6−1
@@ -260,11 +260,14 @@ static u64 get_sideband_reg_base_addr(void) · 259 unmodified lines
260 }260 }
261}261}
262 262
263#define DNV_MCHBAR_SIZE 0x8000
264#define DNV_SB_PORT_SIZE 0x10000
263static int dnv_rd_reg(int port, int off, int op, void *data, size_t sz, char *name)265static int dnv_rd_reg(int port, int off, int op, void *data, size_t sz, char *name)
264{266{
265 struct pci_dev *pdev;267 struct pci_dev *pdev;
266 char *base;268 char *base;
267 u64 addr;269 u64 addr;
270 unsigned long size;
268 271
269 if (op == 4) {272 if (op == 4) {
270 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x1980, NULL);273 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x1980, NULL);
@@ -279,15 +282,17 @@ static int dnv_rd_reg(int port, int off, int op, void *data, size_t sz, char *na · 8 unmodified lines
279 addr = get_mem_ctrl_hub_base_addr();282 addr = get_mem_ctrl_hub_base_addr();
280 if (!addr)283 if (!addr)
281 return -ENODEV;284 return -ENODEV;
285 size = DNV_MCHBAR_SIZE;
282 } else {286 } else {
283 /* MMIO via sideband register base address */287 /* MMIO via sideband register base address */
284 addr = get_sideband_reg_base_addr();288 addr = get_sideband_reg_base_addr();
285 if (!addr)289 if (!addr)
286 return -ENODEV;290 return -ENODEV;
287 addr += (port << 16);291 addr += (port << 16);
292 size = DNV_SB_PORT_SIZE;
288 }293 }
289 294
290 base = ioremap((resource_size_t)addr, 0x10000);295 base = ioremap((resource_size_t)addr, size);
291 if (!base)296 if (!base)
292 return -ENODEV;297 return -ENODEV;
293 298
include/linux/edac.h+5−5
@@ -440,7 +440,7 @@ struct dimm_info { · 439 unmodified lines
440 char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */440 char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
441 441
442 /* Memory location data */442 /* Memory location data */
443 unsigned location[EDAC_MAX_LAYERS];443 unsigned int location[EDAC_MAX_LAYERS];
444 444
445 struct mem_ctl_info *mci; /* the parent */445 struct mem_ctl_info *mci; /* the parent */
446 446
@@ -451,7 +451,7 @@ struct dimm_info { · 4 unmodified lines
451 451
452 u32 nr_pages; /* number of pages on this dimm */452 u32 nr_pages; /* number of pages on this dimm */
453 453
454 unsigned csrow, cschannel; /* Points to the old API data */454 unsigned int csrow, cschannel; /* Points to the old API data */
455 455
456 u16 smbios_handle; /* Handle for SMBIOS type 17 */456 u16 smbios_handle; /* Handle for SMBIOS type 17 */
457};457};
@@ -597,7 +597,7 @@ struct mem_ctl_info { · 139 unmodified lines
597 unsigned long page);597 unsigned long page);
598 int mc_idx;598 int mc_idx;
599 struct csrow_info **csrows;599 struct csrow_info **csrows;
600 unsigned nr_csrows, num_cschannel;600 unsigned int nr_csrows, num_cschannel;
601 601
602 /*602 /*
603 * Memory Controller hierarchy603 * Memory Controller hierarchy
@@ -608,14 +608,14 @@ struct mem_ctl_info { · 4 unmodified lines
608 * of the recent drivers enumerate memories per DIMM, instead.608 * of the recent drivers enumerate memories per DIMM, instead.
609 * When the memory controller is per rank, csbased is true.609 * When the memory controller is per rank, csbased is true.
610 */610 */
611 unsigned n_layers;611 unsigned int n_layers;
612 struct edac_mc_layer *layers;612 struct edac_mc_layer *layers;
613 bool csbased;613 bool csbased;
614 614
615 /*615 /*
616 * DIMM info. Will eventually remove the entire csrows_info some day616 * DIMM info. Will eventually remove the entire csrows_info some day
617 */617 */
618 unsigned tot_dimms;618 unsigned int tot_dimms;
619 struct dimm_info **dimms;619 struct dimm_info **dimms;
620 620
621 /*621 /*

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t