On 10/09/2018 03:36 PM, Michael Bringmann wrote: > powerpc/drmem: Export many of the functions of DRMEM to parse > "ibm,dynamic-memory" and "ibm,dynamic-memory-v2" during hotplug > operations and for Post Migration events. > > Also modify the DRMEM initialization code to allow it to, > > * Be called after system initialization > * Provide a separate user copy of the LMB array that is produces > * Free the user copy upon request > > In addition, a couple of changes were made to make the creation > of additional copies of the LMB array more useful including, > > * Add new iterator to work through a pair of drmem_info arrays. > * Modify DRMEM code to replace usages of dt_root_addr_cells, and > dt_mem_next_cell, as these are only available at first boot. > > Signed-off-by: Michael Bringmann <m...@linux.vnet.ibm.com> > --- > arch/powerpc/include/asm/drmem.h | 15 ++++++++ > arch/powerpc/mm/drmem.c | 75 > ++++++++++++++++++++++++++++---------- > 2 files changed, 70 insertions(+), 20 deletions(-) > > diff --git a/arch/powerpc/include/asm/drmem.h > b/arch/powerpc/include/asm/drmem.h > index 7c1d8e7..1fbb684 100644 > --- a/arch/powerpc/include/asm/drmem.h > +++ b/arch/powerpc/include/asm/drmem.h > @@ -35,6 +35,18 @@ struct drmem_lmb_info { > &drmem_info->lmbs[0], \ > &drmem_info->lmbs[drmem_info->n_lmbs - 1]) > > +#define for_each_dinfo_lmb(dinfo, lmb) \ > + for_each_drmem_lmb_in_range((lmb), \ > + &dinfo->lmbs[0], \ > + &dinfo->lmbs[dinfo->n_lmbs - 1]) > + > +#define for_each_pair_dinfo_lmb(dinfo1, lmb1, dinfo2, lmb2) \ > + for ((lmb1) = (&dinfo1->lmbs[0]), \ > + (lmb2) = (&dinfo2->lmbs[0]); \ > + ((lmb1) <= (&dinfo1->lmbs[dinfo1->n_lmbs - 1])) && \ > + ((lmb2) <= (&dinfo2->lmbs[dinfo2->n_lmbs - 1])); \ > + (lmb1)++, (lmb2)++) > +
The macros for traversing seem to be getting a bit unwieldy with these updates. I wonder if we should move to just using walk routine for all traversing of the drmem lmbs. > /* > * The of_drconf_cell_v1 struct defines the layout of the LMB data > * specified in the ibm,dynamic-memory device tree property. > @@ -94,6 +106,9 @@ void __init walk_drmem_lmbs(struct device_node *dn, > void (*func)(struct drmem_lmb *, const __be32 **)); > int drmem_update_dt(void); > > +struct drmem_lmb_info *drmem_lmbs_init(struct property *prop); > +void drmem_lmbs_free(struct drmem_lmb_info *dinfo); > + > #ifdef CONFIG_PPC_PSERIES > void __init walk_drmem_lmbs_early(unsigned long node, > void (*func)(struct drmem_lmb *, const __be32 **)); > diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c > index 3f18036..13d2abb 100644 > --- a/arch/powerpc/mm/drmem.c > +++ b/arch/powerpc/mm/drmem.c > @@ -20,6 +20,7 @@ > > static struct drmem_lmb_info __drmem_info; > struct drmem_lmb_info *drmem_info = &__drmem_info; > +static int n_root_addr_cells; > > u64 drmem_lmb_memory_max(void) > { > @@ -193,12 +194,13 @@ int drmem_update_dt(void) > return rc; > } > > -static void __init read_drconf_v1_cell(struct drmem_lmb *lmb, > +static void read_drconf_v1_cell(struct drmem_lmb *lmb, > const __be32 **prop) > { > const __be32 *p = *prop; > > - lmb->base_addr = dt_mem_next_cell(dt_root_addr_cells, &p); > + lmb->base_addr = of_read_number(p, n_root_addr_cells); > + p += n_root_addr_cells; Any reason this can't just be lmb->base_addr= dt_mem_next_cell(n_root_addr_cells, &p); > lmb->drc_index = of_read_number(p++, 1); > > p++; /* skip reserved field */ > @@ -209,7 +211,7 @@ static void __init read_drconf_v1_cell(struct drmem_lmb > *lmb, > *prop = p; > } > > -static void __init __walk_drmem_v1_lmbs(const __be32 *prop, const __be32 > *usm, > +static void __walk_drmem_v1_lmbs(const __be32 *prop, const __be32 *usm, > void (*func)(struct drmem_lmb *, const __be32 **)) > { > struct drmem_lmb lmb; > @@ -225,13 +227,14 @@ static void __init __walk_drmem_v1_lmbs(const __be32 > *prop, const __be32 *usm, > } > } > > -static void __init read_drconf_v2_cell(struct of_drconf_cell_v2 *dr_cell, > +static void read_drconf_v2_cell(struct of_drconf_cell_v2 *dr_cell, > const __be32 **prop) > { > const __be32 *p = *prop; > > dr_cell->seq_lmbs = of_read_number(p++, 1); > - dr_cell->base_addr = dt_mem_next_cell(dt_root_addr_cells, &p); > + dr_cell->base_addr = of_read_number(p, n_root_addr_cells); > + p += n_root_addr_cells; Same here. -Nathan > 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); > @@ -239,7 +242,7 @@ static void __init read_drconf_v2_cell(struct > of_drconf_cell_v2 *dr_cell, > *prop = p; > } > > -static void __init __walk_drmem_v2_lmbs(const __be32 *prop, const __be32 > *usm, > +static void __walk_drmem_v2_lmbs(const __be32 *prop, const __be32 *usm, > void (*func)(struct drmem_lmb *, const __be32 **)) > { > struct of_drconf_cell_v2 dr_cell; > @@ -275,6 +278,9 @@ void __init walk_drmem_lmbs_early(unsigned long node, > const __be32 *prop, *usm; > int len; > > + if (n_root_addr_cells == 0) > + n_root_addr_cells = dt_root_addr_cells; > + > prop = of_get_flat_dt_prop(node, "ibm,lmb-size", &len); > if (!prop || len < dt_root_size_cells * sizeof(__be32)) > return; > @@ -353,24 +359,26 @@ void __init walk_drmem_lmbs(struct device_node *dn, > } > } > > -static void __init init_drmem_v1_lmbs(const __be32 *prop) > +static void init_drmem_v1_lmbs(const __be32 *prop, > + struct drmem_lmb_info *dinfo) > { > struct drmem_lmb *lmb; >> - drmem_info->n_lmbs = of_read_number(prop++, 1); > - if (drmem_info->n_lmbs == 0) > + dinfo->n_lmbs = of_read_number(prop++, 1); > + if (dinfo->n_lmbs == 0) > return; > > - drmem_info->lmbs = kcalloc(drmem_info->n_lmbs, sizeof(*lmb), > + dinfo->lmbs = kcalloc(dinfo->n_lmbs, sizeof(*lmb), > GFP_KERNEL); > - if (!drmem_info->lmbs) > + if (!dinfo->lmbs) > return; > > - for_each_drmem_lmb(lmb) > + for_each_dinfo_lmb(dinfo, lmb) > read_drconf_v1_cell(lmb, &prop); > } > > -static void __init init_drmem_v2_lmbs(const __be32 *prop) > +static void init_drmem_v2_lmbs(const __be32 *prop, > + struct drmem_lmb_info *dinfo) > { > struct drmem_lmb *lmb; > struct of_drconf_cell_v2 dr_cell; > @@ -386,12 +394,12 @@ static void __init init_drmem_v2_lmbs(const __be32 > *prop) > p = prop; > for (i = 0; i < lmb_sets; i++) { > read_drconf_v2_cell(&dr_cell, &p); > - drmem_info->n_lmbs += dr_cell.seq_lmbs; > + dinfo->n_lmbs += dr_cell.seq_lmbs; > } > > - drmem_info->lmbs = kcalloc(drmem_info->n_lmbs, sizeof(*lmb), > + dinfo->lmbs = kcalloc(dinfo->n_lmbs, sizeof(*lmb), > GFP_KERNEL); > - if (!drmem_info->lmbs) > + if (!dinfo->lmbs) > return; > > /* second pass, read in the LMB information */ > @@ -402,10 +410,10 @@ static void __init init_drmem_v2_lmbs(const __be32 > *prop) > read_drconf_v2_cell(&dr_cell, &p); > > for (j = 0; j < dr_cell.seq_lmbs; j++) { > - lmb = &drmem_info->lmbs[lmb_index++]; > + lmb = &dinfo->lmbs[lmb_index++]; > > lmb->base_addr = dr_cell.base_addr; > - dr_cell.base_addr += drmem_info->lmb_size; > + dr_cell.base_addr += dinfo->lmb_size; > > lmb->drc_index = dr_cell.drc_index; > dr_cell.drc_index++; > @@ -416,11 +424,38 @@ static void __init init_drmem_v2_lmbs(const __be32 > *prop) > } > } > > +void drmem_lmbs_free(struct drmem_lmb_info *dinfo) > +{ > + if (dinfo) { > + kfree(dinfo->lmbs); > + kfree(dinfo); > + } > +} > + > +struct drmem_lmb_info *drmem_lmbs_init(struct property *prop) > +{ > + struct drmem_lmb_info *dinfo; > + > + dinfo = kzalloc(sizeof(*dinfo), GFP_KERNEL); > + if (!dinfo) > + return NULL; > + > + if (!strcmp("ibm,dynamic-memory", prop->name)) > + init_drmem_v1_lmbs(prop->value, dinfo); > + else if (!strcmp("ibm,dynamic-memory-v2", prop->name)) > + init_drmem_v2_lmbs(prop->value, dinfo); > + > + return dinfo; > +} > + > static int __init drmem_init(void) > { > struct device_node *dn; > const __be32 *prop; > > + if (n_root_addr_cells == 0) > + n_root_addr_cells = dt_root_addr_cells; > + > dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); > if (!dn) { > pr_info("No dynamic reconfiguration memory found\n"); > @@ -434,11 +469,11 @@ static int __init drmem_init(void) > > prop = of_get_property(dn, "ibm,dynamic-memory", NULL); > if (prop) { > - init_drmem_v1_lmbs(prop); > + init_drmem_v1_lmbs(prop, drmem_info); > } else { > prop = of_get_property(dn, "ibm,dynamic-memory-v2", NULL); > if (prop) > - init_drmem_v2_lmbs(prop); > + init_drmem_v2_lmbs(prop, drmem_info); > } > > of_node_put(dn); >