From patchwork Tue Oct 3 18:40:16 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Fontenot X-Patchwork-Id: 820992 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 ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y67ly2LvRz9sPm for ; Wed, 4 Oct 2017 06:05:50 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3y67ly1RjtzDrCk for ; Wed, 4 Oct 2017 06:05:50 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.158.5; helo=mx0a-001b2d01.pphosted.com; envelope-from=nfont@linux.vnet.ibm.com; receiver=) Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (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 3y67Vy1LpLzDqks for ; Wed, 4 Oct 2017 05:54:33 +1100 (AEDT) Received: from pps.filterd (m0098420.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id v93InTEj011733 for ; Tue, 3 Oct 2017 14:54:32 -0400 Received: from e13.ny.us.ibm.com (e13.ny.us.ibm.com [129.33.205.203]) by mx0b-001b2d01.pphosted.com with ESMTP id 2dccvkunr4-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 03 Oct 2017 14:54:31 -0400 Received: from localhost by e13.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 3 Oct 2017 14:54:30 -0400 Received: from b01cxnp22033.gho.pok.ibm.com (9.57.198.23) by e13.ny.us.ibm.com (146.89.104.200) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 3 Oct 2017 14:54:28 -0400 Received: from b01ledav001.gho.pok.ibm.com (b01ledav001.gho.pok.ibm.com [9.57.199.106]) by b01cxnp22033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v93IsSFC41353278 for ; Tue, 3 Oct 2017 18:54:28 GMT Received: from b01ledav001.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A8D482803A for ; Tue, 3 Oct 2017 14:54:21 -0400 (EDT) Received: from ltcalpine2-lp14.aus.stglabs.ibm.com (unknown [9.40.195.197]) by b01ledav001.gho.pok.ibm.com (Postfix) with ESMTP id 7FED02804C for ; Tue, 3 Oct 2017 14:54:21 -0400 (EDT) Subject: [PATCH7/8] powerpc/pseries: Add support for ibm, dynamic-memory-v2 property From: Nathan Fontenot To: linuxppc-dev@lists.ozlabs.org Date: Tue, 03 Oct 2017 13:40:16 -0500 In-Reply-To: <150705593139.7318.5934648279979743833.stgit@ltcalpine2-lp14.aus.stglabs.ibm.com> References: <150705593139.7318.5934648279979743833.stgit@ltcalpine2-lp14.aus.stglabs.ibm.com> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 17100318-0008-0000-0000-0000028A636F X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00007836; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000233; SDB=6.00926015; UDB=6.00465781; IPR=6.00706215; BA=6.00005620; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00017383; XFM=3.00000015; UTC=2017-10-03 18:54:29 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17100318-0009-0000-0000-000036E5798D Message-Id: <150705601647.7318.2462819659401153641.stgit@ltcalpine2-lp14.aus.stglabs.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-10-03_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000 definitions=main-1710030266 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.24 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" The Power Hypervisor has introduced a new device tree format for the property describing the dynamic reconfiguration LMBs for a system. This new format condenses the size of the property, especially on large memory systems, to provide an entry per range of LMBs that possess the same flags and associativity index instead of specifying an entry per LMB. This patch updates the drmem code to be able to parse the new property format at boot and create the LMB array. This also updates the device tree updating routine to build a device tree property in this format. Signed-off-by: Nathan Fontenot --- arch/powerpc/include/asm/drmem.h | 12 ++ arch/powerpc/mm/drmem.c | 188 ++++++++++++++++++++++++++++++++++---- 2 files changed, 182 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h index 32d859c84202..b7becafc528d 100644 --- a/arch/powerpc/include/asm/drmem.h +++ b/arch/powerpc/include/asm/drmem.h @@ -49,6 +49,18 @@ struct of_drconf_cell_v1 { u32 flags; }; +/* Version 2 of the ibm,dynamic-memory property is defined as a + * 32-bit value specifying the number of LMB sets followed by an + * array of of_drconf_cell_v2 entries, one per LMB set. + */ +struct of_drconf_cell_v2 { + u32 seq_lmbs; + u64 base_addr; + u32 drc_index; + u32 aa_index; + u32 flags; +} __attribute__((packed)); + #define DRCONF_MEM_ASSIGNED 0x00000008 #define DRCONF_MEM_AI_INVALID 0x00000040 #define DRCONF_MEM_RESERVED 0x00000080 diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c index 9cd9e680874e..b5b8b8f46292 100644 --- a/arch/powerpc/mm/drmem.c +++ b/arch/powerpc/mm/drmem.c @@ -21,25 +21,13 @@ static struct drmem_lmb_info __drmem_info; struct drmem_lmb_info *drmem_info = &__drmem_info; -int __init init_drmem_lmbs(unsigned long node) +static int __init init_drmem_lmbs_v1(const __be32 *prop, u32 len) { struct drmem_lmb *lmb; - const __be32 *prop; - int prop_sz; - u32 len; - - prop = of_get_flat_dt_prop(node, "ibm,lmb-size", &len); - if (!prop || len < dt_root_size_cells * sizeof(__be32)) - return -1; - - drmem_info->lmb_size = dt_mem_next_cell(dt_root_size_cells, &prop); - - prop = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &len); - if (!prop || len < dt_root_size_cells * sizeof(__be32)) - return -1; + u32 prop_sz; drmem_info->n_lmbs = of_read_number(prop++, 1); - prop_sz = drmem_info->n_lmbs * sizeof(struct of_drconf_cell) + prop_sz = drmem_info->n_lmbs * sizeof(struct of_drconf_cell_v1) + sizeof(__be32); if (prop_sz < len) return -1; @@ -61,6 +49,89 @@ int __init init_drmem_lmbs(unsigned long node) return 0; } +static void read_one_drconf_v2_cell(const __be32 **cell, + struct of_drconf_cell_v2 *dr_cell) +{ + const __be32 *p = *cell; + + dr_cell->seq_lmbs = of_read_number(p++, 1); + dr_cell->base_addr = dt_mem_next_cell(dt_root_addr_cells, &p); + dr_cell->drc_index = of_read_number(p++, 1); + dr_cell->aa_index = of_read_number(p++, 1); + dr_cell->flags = of_read_number(p++, 1); + + *cell = p; +} + +static int __init init_drmem_lmbs_v2(const __be32 *prop, u32 len) +{ + struct drmem_lmb *lmb; + struct of_drconf_cell_v2 dr_cell; + const __be32 *p; + u32 lmb_sets, prop_sz; + int i, j, lmb_index; + + lmb_sets = of_read_number(prop++, 1); + prop_sz = lmb_sets * sizeof(struct of_drconf_cell_v2) + + sizeof(__be32); + if (prop_sz < len) + return -1; + + /* first pass, calculate the number of LMBs */ + p = prop; + for (i = 0; i < lmb_sets; i++) { + read_one_drconf_v2_cell(&p, &dr_cell); + drmem_info->n_lmbs += dr_cell.seq_lmbs; + } + + drmem_info->lmbs = alloc_bootmem(drmem_info->n_lmbs * sizeof(*lmb)); + if (!drmem_info->lmbs) + return -1; + + lmb_index = 0; + p = prop; + for (i = 0; i < lmb_sets; i++) { + read_one_drconf_v2_cell(&p, &dr_cell); + + for (j = 0; j < dr_cell.seq_lmbs; j++) { + lmb = &drmem_info->lmbs[lmb_index++]; + + lmb->base_addr = dr_cell.base_addr; + dr_cell.base_addr += drmem_info->lmb_size; + + lmb->drc_index = dr_cell.drc_index; + dr_cell.drc_index++; + + lmb->aa_index = dr_cell.aa_index; + lmb->flags = dr_cell.flags; + } + } + + return 0; +} + +int __init init_drmem_lmbs(unsigned long node) +{ + const __be32 *prop; + u32 len; + + prop = of_get_flat_dt_prop(node, "ibm,lmb-size", &len); + if (!prop || len < dt_root_size_cells * sizeof(__be32)) + return -1; + + drmem_info->lmb_size = dt_mem_next_cell(dt_root_size_cells, &prop); + + prop = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &len); + if (prop) + return init_drmem_lmbs_v1(prop, len); + + prop = of_get_flat_dt_prop(node, "ibm,dynamic-memory-v2", &len); + if (prop) + return init_drmem_lmbs_v2(prop, len); + + return -1; +} + u64 drmem_lmb_memory_max(void) { struct drmem_lmb *last_lmb; @@ -130,6 +201,82 @@ static int drmem_update_dt_v1(struct device_node *memory, return 0; } +static void init_drconf_v2_cell(struct of_drconf_cell_v2 *dr_cell, + struct drmem_lmb *lmb) +{ + dr_cell->base_addr = cpu_to_be64(lmb->base_addr); + dr_cell->drc_index = cpu_to_be32(lmb->drc_index); + dr_cell->aa_index = cpu_to_be32(lmb->aa_index); + dr_cell->flags = cpu_to_be32(lmb->flags); +} + +static int drmem_update_dt_v2(struct device_node *memory, + struct property *prop) +{ + struct property *new_prop; + struct of_drconf_cell_v2 *dr_cell; + struct drmem_lmb *lmb, *prev_lmb; + u32 lmb_sets, prop_sz, seq_lmbs; + u32 *p; + + lmb_sets = 0; + prev_lmb = NULL; + for_each_drmem_lmb(lmb) { + if (!prev_lmb) { + prev_lmb = lmb; + lmb_sets++; + continue; + } + + if (prev_lmb->aa_index != lmb->aa_index || + prev_lmb->flags != drmem_lmb_flags(lmb)) + lmb_sets++; + + prev_lmb = lmb; + } + + prop_sz = lmb_sets * sizeof(*dr_cell) + sizeof(__be32); + new_prop = clone_property(prop, prop_sz); + if (!new_prop) + return -1; + + p = new_prop->value; + *p++ = cpu_to_be32(lmb_sets); + + dr_cell = (struct of_drconf_cell_v2 *)p; + + prev_lmb = NULL; + seq_lmbs = 0; + for_each_drmem_lmb(lmb) { + if (prev_lmb == NULL) { + /* Start of first set */ + prev_lmb = lmb; + init_drconf_v2_cell(dr_cell, lmb); + seq_lmbs++; + continue; + } + + if (prev_lmb->aa_index != lmb->aa_index || + prev_lmb->flags != drmem_lmb_flags(lmb)) { + /* end of one set, start of another */ + dr_cell->seq_lmbs = cpu_to_be32(seq_lmbs); + dr_cell++; + + init_drconf_v2_cell(dr_cell, lmb); + seq_lmbs = 1; + } else { + seq_lmbs++; + } + + prev_lmb = lmb; + } + + /* close out last dr_cell */ + dr_cell->seq_lmbs = cpu_to_be32(seq_lmbs); + of_update_property(memory, new_prop); + return 0; +} + int drmem_update_dt(void) { struct device_node *memory; @@ -141,10 +288,15 @@ int drmem_update_dt(void) return -1; prop = of_find_property(memory, "ibm,dynamic-memory", NULL); - if (prop) + if (prop) { rc = drmem_update_dt_v1(memory, prop); - else - rc = -1; + } else { + prop = of_find_property(memory, "ibm,dynamic-memory-v2", NULL); + if (prop) + rc = drmem_update_dt_v2(memory, prop); + else + rc = -1; + } of_node_put(memory); return rc;