From: "Ghannam, Yazen" <Yazen.Ghannam@amd.com> To: "linux-edac@vger.kernel.org" <linux-edac@vger.kernel.org> Cc: "Ghannam, Yazen" <Yazen.Ghannam@amd.com>, "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>, "bp@alien8.de" <bp@alien8.de> Subject: [PATCH v3 2/5] EDAC/amd64: Gather hardware information early Date: Wed, 6 Nov 2019 01:25:00 +0000 Message-ID: <20191106012448.243970-3-Yazen.Ghannam@amd.com> (raw) In-Reply-To: <20191106012448.243970-1-Yazen.Ghannam@amd.com> From: Yazen Ghannam <yazen.ghannam@amd.com> Split out gathering hardware information from init_one_instance() into a separate function hw_info_get(). This is necessary so that the information can be cached earlier and used to check if memory is populated and if ECC is enabled on a node. Also, define a function hw_info_put() to back out changes made in hw_info_get(). Currently, this includes two actions: freeing reserved PCI device siblings and freeing the allocated struct amd64_umc. Check for an allocated PCI device (Function 0 for Family 17h or Function 1 for pre-Family 17h) before freeing, since hw_info_put() may be called before PCI siblings are reserved. Drop the family check when freeing pvt->umc. This will be NULL on pre-Family 17h systems. However, kfree() is safe and will check for a NULL pointer before freeing. Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com> --- Link: https://lkml.kernel.org/r/20191022203448.13962-3-Yazen.Ghannam@amd.com v2 -> v3: * No change. v1 -> v2: * Change get_hardware_info() to hw_info_get(). * Add hw_info_put() to backout changes from hw_info_get(). rfc -> v1: * Fixup after making struct amd64_family_type fam_type global. drivers/edac/amd64_edac.c | 101 +++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 83c659e38084..6e1c739b7fad 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3418,34 +3418,15 @@ static void compute_num_umcs(void) edac_dbg(1, "Number of UMCs: %x", num_umcs); } -static int init_one_instance(unsigned int nid) +static int hw_info_get(struct amd64_pvt *pvt) { - struct pci_dev *F3 = node_to_amd_nb(nid)->misc; - struct mem_ctl_info *mci = NULL; - struct edac_mc_layer layers[2]; - struct amd64_pvt *pvt = NULL; u16 pci_id1, pci_id2; - int err = 0, ret; - - ret = -ENOMEM; - pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); - if (!pvt) - goto err_ret; - - pvt->mc_node_id = nid; - pvt->F3 = F3; - - ret = -EINVAL; - fam_type = per_family_init(pvt); - if (!fam_type) - goto err_free; + int ret = -EINVAL; if (pvt->fam >= 0x17) { pvt->umc = kcalloc(num_umcs, sizeof(struct amd64_umc), GFP_KERNEL); - if (!pvt->umc) { - ret = -ENOMEM; - goto err_free; - } + if (!pvt->umc) + return -ENOMEM; pci_id1 = fam_type->f0_id; pci_id2 = fam_type->f6_id; @@ -3454,21 +3435,37 @@ static int init_one_instance(unsigned int nid) pci_id2 = fam_type->f2_id; } - err = reserve_mc_sibling_devs(pvt, pci_id1, pci_id2); - if (err) - goto err_post_init; + ret = reserve_mc_sibling_devs(pvt, pci_id1, pci_id2); + if (ret) + return ret; read_mc_regs(pvt); + return 0; +} + +static void hw_info_put(struct amd64_pvt *pvt) +{ + if (pvt->F0 || pvt->F1) + free_mc_sibling_devs(pvt); + + kfree(pvt->umc); +} + +static int init_one_instance(struct amd64_pvt *pvt) +{ + struct mem_ctl_info *mci = NULL; + struct edac_mc_layer layers[2]; + int ret = -EINVAL; + /* * We need to determine how many memory channels there are. Then use * that information for calculating the size of the dynamic instance * tables in the 'mci' structure. */ - ret = -EINVAL; pvt->channel_count = pvt->ops->early_channel_count(pvt); if (pvt->channel_count < 0) - goto err_siblings; + return ret; ret = -ENOMEM; layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; @@ -3490,9 +3487,9 @@ static int init_one_instance(unsigned int nid) layers[1].size = 2; layers[1].is_virt_csrow = false; - mci = edac_mc_alloc(nid, ARRAY_SIZE(layers), layers, 0); + mci = edac_mc_alloc(pvt->mc_node_id, ARRAY_SIZE(layers), layers, 0); if (!mci) - goto err_siblings; + return ret; mci->pvt_info = pvt; mci->pdev = &pvt->F3->dev; @@ -3505,31 +3502,17 @@ static int init_one_instance(unsigned int nid) ret = -ENODEV; if (edac_mc_add_mc_with_groups(mci, amd64_edac_attr_groups)) { edac_dbg(1, "failed edac_mc_add_mc()\n"); - goto err_add_mc; + edac_mc_free(mci); + return ret; } return 0; - -err_add_mc: - edac_mc_free(mci); - -err_siblings: - free_mc_sibling_devs(pvt); - -err_post_init: - if (pvt->fam >= 0x17) - kfree(pvt->umc); - -err_free: - kfree(pvt); - -err_ret: - return ret; } static int probe_one_instance(unsigned int nid) { struct pci_dev *F3 = node_to_amd_nb(nid)->misc; + struct amd64_pvt *pvt = NULL; struct ecc_settings *s; int ret; @@ -3540,6 +3523,21 @@ static int probe_one_instance(unsigned int nid) ecc_stngs[nid] = s; + pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); + if (!pvt) + goto err_settings; + + pvt->mc_node_id = nid; + pvt->F3 = F3; + + fam_type = per_family_init(pvt); + if (!fam_type) + goto err_enable; + + ret = hw_info_get(pvt); + if (ret < 0) + goto err_enable; + if (!ecc_enabled(F3, nid)) { ret = 0; @@ -3556,7 +3554,7 @@ static int probe_one_instance(unsigned int nid) goto err_enable; } - ret = init_one_instance(nid); + ret = init_one_instance(pvt); if (ret < 0) { amd64_err("Error probing instance: %d\n", nid); @@ -3569,6 +3567,10 @@ static int probe_one_instance(unsigned int nid) return ret; err_enable: + hw_info_put(pvt); + kfree(pvt); + +err_settings: kfree(s); ecc_stngs[nid] = NULL; @@ -3595,14 +3597,13 @@ static void remove_one_instance(unsigned int nid) restore_ecc_error_reporting(s, nid, F3); - free_mc_sibling_devs(pvt); - kfree(ecc_stngs[nid]); ecc_stngs[nid] = NULL; /* Free the EDAC CORE resources */ mci->pvt_info = NULL; + hw_info_put(pvt); kfree(pvt); edac_mc_free(mci); } -- 2.17.1
next prev parent reply index Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-11-06 1:24 [PATCH v3 0/5] AMD64 EDAC: Check for nodes without memory, etc Ghannam, Yazen 2019-11-06 1:24 ` [PATCH v3 1/5] EDAC/amd64: Make struct amd64_family_type global Ghannam, Yazen 2019-11-06 1:25 ` Ghannam, Yazen [this message] 2019-11-06 1:25 ` [PATCH v3 3/5] EDAC/amd64: Save max number of controllers to family type Ghannam, Yazen 2019-11-06 1:25 ` [PATCH v3 4/5] EDAC/amd64: Use cached data when checking for ECC Ghannam, Yazen 2019-11-06 1:25 ` [PATCH v3 5/5] EDAC/amd64: Check for memory before fully initializing an instance Ghannam, Yazen 2019-11-06 16:06 ` [PATCH v3 0/5] AMD64 EDAC: Check for nodes without memory, etc Borislav Petkov 2019-11-06 18:16 ` Ghannam, Yazen 2019-11-06 19:54 ` Borislav Petkov 2019-11-07 10:38 ` Borislav Petkov 2019-11-07 13:47 ` Ghannam, Yazen 2019-11-07 15:40 ` Borislav Petkov 2019-11-07 19:20 ` Ghannam, Yazen 2019-11-07 19:34 ` Borislav Petkov 2019-11-07 19:41 ` Ghannam, Yazen 2019-11-09 9:08 ` [PATCH] EDAC/amd64: Get rid of the ECC disabled long message Borislav Petkov
Reply instructions: You may reply publically to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20191106012448.243970-3-Yazen.Ghannam@amd.com \ --to=yazen.ghannam@amd.com \ --cc=bp@alien8.de \ --cc=linux-edac@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Linux-EDAC Archive on lore.kernel.org Archives are clonable: git clone --mirror https://lore.kernel.org/linux-edac/0 linux-edac/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 linux-edac linux-edac/ https://lore.kernel.org/linux-edac \ linux-edac@vger.kernel.org public-inbox-index linux-edac Example config snippet for mirrors Newsgroup available over NNTP: nntp://nntp.lore.kernel.org/org.kernel.vger.linux-edac AGPL code for this site: git clone https://public-inbox.org/public-inbox.git