From patchwork Wed Sep 21 14:17:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Bringmann X-Patchwork-Id: 672905 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sfMKC4FL1z9sQw for ; Thu, 22 Sep 2016 00:22:39 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3sfMKC3LKxzDsm7 for ; Thu, 22 Sep 2016 00:22:39 +1000 (AEST) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3sfMCP1DH1zDsj5 for ; Thu, 22 Sep 2016 00:17:36 +1000 (AEST) Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.17/8.16.0.17) with SMTP id u8LEDkPd041400 for ; Wed, 21 Sep 2016 10:17:35 -0400 Received: from e17.ny.us.ibm.com (e17.ny.us.ibm.com [129.33.205.207]) by mx0a-001b2d01.pphosted.com with ESMTP id 25kurq89an-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Wed, 21 Sep 2016 10:17:35 -0400 Received: from localhost by e17.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 21 Sep 2016 10:17:32 -0400 Received: from d01dlp03.pok.ibm.com (9.56.250.168) by e17.ny.us.ibm.com (146.89.104.204) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 21 Sep 2016 10:17:30 -0400 Received: from b01cxnp22036.gho.pok.ibm.com (b01cxnp22036.gho.pok.ibm.com [9.57.198.26]) by d01dlp03.pok.ibm.com (Postfix) with ESMTP id 0CC29C90057 for ; Wed, 21 Sep 2016 10:17:16 -0400 (EDT) Received: from b01ledav001.gho.pok.ibm.com (b01ledav001.gho.pok.ibm.com [9.57.199.106]) by b01cxnp22036.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u8LEHBWc15925586; Wed, 21 Sep 2016 14:17:28 GMT Received: from b01ledav001.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 782FF2806D; Wed, 21 Sep 2016 10:17:28 -0400 (EDT) Received: from oc1376853207.ibm.com (unknown [9.53.92.233]) by b01ledav001.gho.pok.ibm.com (Postfix) with ESMTP id 2C03C28060; Wed, 21 Sep 2016 10:17:28 -0400 (EDT) To: linuxppc-dev@lists.ozlabs.org, Nathan Fontenot , Michael Bringmann From: Michael Bringmann Subject: [PATCH V6 3/8] powerpc/memory: Parse new memory property to initialize structures. Organization: IBM Linux Technology Center Date: Wed, 21 Sep 2016 09:17:27 -0500 User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16092114-0040-0000-0000-00000165381E X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00005797; HX=3.00000240; KW=3.00000007; PH=3.00000004; SC=3.00000185; SDB=6.00759874; UDB=6.00361328; IPR=6.00534285; BA=6.00004744; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00012737; XFM=3.00000011; UTC=2016-09-21 14:17:31 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16092114-0041-0000-0000-000005584006 Message-Id: X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-09-21_09:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1609020000 definitions=main-1609210260 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" powerpc/memory: Add parallel routines to parse the new property "ibm,dynamic-memory-v2" property when it is present, and then to finish initialization of the relevant memory structures with the operating system. This code is shared between the boot-time initialization functions and the runtime functions for memory hotplug, so it needs to be able to handle both formats. [V2: Revise contant names.] [V3: Fix loop that needed to scan all blocks defined by new, compressed memory definition. [V4: Added external function prototype definitions to header file "prom.h" for use in other files. Change a firmware architure vec check for scan actual device tree. Delete an unused variable. Small cleanups to comments.] [V5: Resynchronize/resubmit] [V6: No change] Signed-off-by: Michael Bringmann diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h index 7f436ba..b9a1534 100644 --- a/arch/powerpc/include/asm/prom.h +++ b/arch/powerpc/include/asm/prom.h @@ -109,6 +109,18 @@ struct of_drconf_cell_v2 { extern void read_drconf_cell_v2(struct of_drconf_cell_v2 *drmem, const __be32 **cellp); + +extern void read_one_drc_info(int **info, char **drc_type, char **drc_name, + unsigned long int *fdi_p, unsigned long int *nsl_p, + unsigned long int *si_p, unsigned long int *ldi_p); + +static inline int dyn_mem_v2_len(int entries) +{ + int drconf_v2_cells = (n_mem_addr_cells + 4); + int drconf_v2_cells_len = (drconf_v2_cells * sizeof(unsigned int)); + return (((entries) * drconf_v2_cells_len) + + (1 * sizeof(unsigned int))); +} /* * There are two methods for telling firmware what our capabilities are. diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 669a15e..18b4ee7 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -427,30 +426,55 @@ EXPORT_SYMBOL(read_drconf_cell_v2); /* - * Retrieve and validate the ibm,dynamic-memory property of the device tree. + * Retrieve and validate the ibm,dynamic-memory[-v2] property of the + * device tree. + * + * The layout of the ibm,dynamic-memory property is a number N of memory + * block description list entries followed by N memory block description + * list entries. Each memory block description list entry contains + * information as laid out in the of_drconf_cell struct above. * - * The layout of the ibm,dynamic-memory property is a number N of memblock - * list entries followed by N memblock list entries. Each memblock list entry - * contains information as laid out in the of_drconf_cell struct above. + * The layout of the ibm,dynamic-memory-v2 property is a number N of memory + * block set description list entries, followed by N memory block set + * description set entries. */ static int of_get_drconf_memory(struct device_node *memory, const __be32 **dm) { const __be32 *prop; u32 len, entries; - prop = of_get_property(memory, "ibm,dynamic-memory", &len); - if (!prop || len < sizeof(unsigned int)) - return 0; + if (firmware_has_feature(FW_FEATURE_DYN_MEM_V2)) { - entries = of_read_number(prop++, 1); + prop = of_get_property(memory, "ibm,dynamic-memory-v2", &len); + if (!prop || len < sizeof(unsigned int)) + return 0; - /* Now that we know the number of entries, revalidate the size - * of the property read in to ensure we have everything - */ - if (len < (entries * (n_mem_addr_cells + 4) + 1) * sizeof(unsigned int)) - return 0; + entries = of_read_number(prop++, 1); + + /* Now that we know the number of set entries, revalidate the + * size of the property read in to ensure we have everything. + */ + if (len < dyn_mem_v2_len(entries)) + return 0; + + *dm = prop; + } else { + prop = of_get_property(memory, "ibm,dynamic-memory", &len); + if (!prop || len < sizeof(unsigned int)) + return 0; + + entries = of_read_number(prop++, 1); + + /* Now that we know the number of entries, revalidate the size + * of the property read in to ensure we have everything + */ + if (len < (entries * (n_mem_addr_cells + 4) + 1) * + sizeof(unsigned int)) + return 0; + + *dm = prop; + } - *dm = prop; return entries; } @@ -513,7 +537,7 @@ * This is like of_node_to_nid_single() for memory represented in the * ibm,dynamic-reconfiguration-memory node. */ -static int of_drconf_to_nid_single(struct of_drconf_cell *drmem, +static int of_drconf_to_nid_single(u32 drmem_flags, u32 drmem_aa_index, struct assoc_arrays *aa) { int default_nid = 0; @@ -521,16 +545,16 @@ int index; if (min_common_depth > 0 && min_common_depth <= aa->array_sz && - !(drmem->flags & DRCONF_MEM_AI_INVALID) && - drmem->aa_index < aa->n_arrays) { - index = drmem->aa_index * aa->array_sz + min_common_depth - 1; + !(drmem_flags & DRCONF_MEM_AI_INVALID) && + drmem_aa_index < aa->n_arrays) { + index = drmem_aa_index * aa->array_sz + min_common_depth - 1; nid = of_read_number(&aa->arrays[index], 1); if (nid == 0xffff || nid >= MAX_NUMNODES) nid = default_nid; if (nid > 0) { - index = drmem->aa_index * aa->array_sz; + index = drmem_aa_index * aa->array_sz; initialize_distance_lookup_table(nid, &aa->arrays[index]); } @@ -665,7 +697,7 @@ * Extract NUMA information from the ibm,dynamic-reconfiguration-memory * node. This assumes n_mem_{addr,size}_cells have been set. */ -static void __init parse_drconf_memory(struct device_node *memory) +static void __init parse_drconf_memory_v1(struct device_node *memory) { const __be32 *uninitialized_var(dm), *usm; unsigned int n, rc, ranges, is_kexec_kdump = 0; @@ -715,10 +747,11 @@ base = read_n_cells(n_mem_addr_cells, &usm); size = read_n_cells(n_mem_size_cells, &usm); } - nid = of_drconf_to_nid_single(&drmem, &aa); + nid = of_drconf_to_nid_single(drmem.flags, + drmem.aa_index, &aa); fake_numa_create_new_node( ((base + size) >> PAGE_SHIFT), &nid); node_set_online(nid); sz = numa_enforce_memory_limit(base, size); if (sz) @@ -728,6 +761,80 @@ } } +static void __init parse_drconf_memory_v2(struct device_node *memory) +{ + const __be32 *uninitialized_var(dm); + unsigned int num_lmb_sets, rc; + unsigned long lmb_size, base; + unsigned long size, sz; + int nid; + struct assoc_arrays aa = { .arrays = NULL }; + const __be32 *prop; + u32 len; + + prop = of_get_property(memory, "ibm,dynamic-memory-v2", &len); + if (!prop) + return; + + num_lmb_sets = of_get_drconf_memory(memory, &dm); + if (!num_lmb_sets) + return; + + lmb_size = of_get_lmb_size(memory); + if (!lmb_size) + return; + + rc = of_get_assoc_arrays(memory, &aa); + if (rc) + return; + + for (; num_lmb_sets != 0; num_lmb_sets--) { + struct of_drconf_cell_v2 drmem; + unsigned long nsl; + + /* Get the current LMB set */ + read_drconf_cell_v2(&drmem, &dm); + base = drmem.base_addr; + nsl = drmem.num_seq_lmbs; + + /* Skip this block if the reserved bit is set in + * flags (0x80) or if the block is not assigned + * to this partition (0x8) + */ + if ((drmem.flags & DRCONF_MEM_RESERVED) + || !(drmem.flags & DRCONF_MEM_ASSIGNED)) + continue; + + for (; nsl != 0; nsl--) { + size = lmb_size; + + nid = of_drconf_to_nid_single(drmem.flags, + drmem.aa_index, &aa); + fake_numa_create_new_node( + ((base + size) >> PAGE_SHIFT), + &nid); + node_set_online(nid); + sz = numa_enforce_memory_limit(base, size); + if (sz) + memblock_set_node(base, sz, + &memblock.memory, nid); + + base += sz; + } + } +} + +static void __init parse_drconf_memory(struct device_node *memory) +{ + const __be32 *prop; + int len; + prop = of_get_property(memory, "ibm,dynamic-memory-v2", &len); + if (!prop || len < sizeof(unsigned int)) + parse_drconf_memory_v1(memory); + else + parse_drconf_memory_v2(memory); +} + static int __init parse_numa_properties(void) { struct device_node *memory; @@ -1082,8 +1211,8 @@ static int hot_add_drconf_scn_to_nid(struct device_node *memory, if ((scn_addr < drmem.base_addr) || (scn_addr >= (drmem.base_addr + lmb_size))) continue; - - nid = of_drconf_to_nid_single(&drmem, &aa); + nid = of_drconf_to_nid_single(drmem.flags, + drmem.aa_index, &aa); break; }