On 22/10/17 11:52PM, Rafał Miłecki wrote: > On 17.10.2022 21:59, han.xu wrote: > > On 22/06/06 05:14PM, Ansuel Smith wrote: > > > We have many parser that register mtd partitions at runtime. One example > > > is the cmdlinepart or the smem-part parser where the compatible is defined > > > in the dts and the partitions gets detected and registered by the > > > parser. This is problematic for the NVMEM subsystem that requires an OF node > > > to detect NVMEM cells. > > > > > > To fix this problem, introduce an additional logic that will try to > > > assign an OF node to the MTD if declared. > > > > > > On MTD addition, it will be checked if the MTD has an OF node and if > > > not declared will check if a partition with the same label is > > > declared in DTS. If an exact match is found, the partition dynamically > > > allocated by the parser will have a connected OF node. > > > > > > The NVMEM subsystem will detect the OF node and register any NVMEM cells > > > declared statically in the DTS. > > > > > > Signed-off-by: Ansuel Smith <ansuelsmth@xxxxxxxxx> > > > --- > > > drivers/mtd/mtdcore.c | 49 +++++++++++++++++++++++++++++++++++++++++++ > > > 1 file changed, 49 insertions(+) > > > > > > diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c > > > index 7731796024e0..807194efb580 100644 > > > --- a/drivers/mtd/mtdcore.c > > > +++ b/drivers/mtd/mtdcore.c > > > @@ -546,6 +546,54 @@ static int mtd_nvmem_add(struct mtd_info *mtd) > > > return 0; > > > } > > > +static void mtd_check_of_node(struct mtd_info *mtd) > > > +{ > > > + struct device_node *partitions, *parent_dn, *mtd_dn = NULL; > > > + struct mtd_info *parent; > > > + const char *mtd_name; > > > + bool found = false; > > > + int plen; > > > + > > > + /* Check if MTD already has a device node */ > > > + if (dev_of_node(&mtd->dev)) > > > + return; > > > + > > > + /* Check if a partitions node exist */ > > > + parent = mtd->parent; > > > + parent_dn = dev_of_node(&parent->dev); > > > + if (!parent_dn) > > > + return; > > > + > > > + partitions = of_get_child_by_name(parent_dn, "partitions"); > > > + if (!partitions) > > > + goto exit_parent; > > > + > > > + /* Search if a partition is defined with the same name */ > > > + for_each_child_of_node(partitions, mtd_dn) { > > > + /* Skip partition with no label */ > > > + mtd_name = of_get_property(mtd_dn, "label", &plen); > > > + if (!mtd_name) > > > + continue; > > > + > > > + if (!strncmp(mtd->name, mtd_name, plen)) { > > > + found = true; > > > + break; > > > + } > > > + } > > > + > > > + if (!found) > > > + goto exit_partitions; > > > + > > > + /* Set of_node only for nvmem */ > > > + if (of_device_is_compatible(mtd_dn, "nvmem-cells")) > > > + mtd_set_of_node(mtd, mtd_dn); > > > + > > > +exit_partitions: > > > + of_node_put(partitions); > > > +exit_parent: > > > + of_node_put(parent_dn); > > > +} > > > + > > > /** > > > * add_mtd_device - register an MTD device > > > * @mtd: pointer to new MTD device info structure > > > @@ -651,6 +699,7 @@ int add_mtd_device(struct mtd_info *mtd) > > > mtd->dev.devt = MTD_DEVT(i); > > > dev_set_name(&mtd->dev, "mtd%d", i); > > > dev_set_drvdata(&mtd->dev, mtd); > > > + mtd_check_of_node(mtd); > > > of_node_get(mtd_get_of_node(mtd)); > > > error = device_register(&mtd->dev); > > > if (error) > > > > NXP GPMI NAND controller with 6 cmdline partitions meets refcount underflow > > with this patch. The of_node_put(parent_dn) doesn't work with cmdline parser and > > causes the issue. > > Can you try: > > diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c > index 18aa54460d36..0b4ca0aa4132 100644 > --- a/drivers/mtd/mtdcore.c > +++ b/drivers/mtd/mtdcore.c > @@ -562,7 +562,7 @@ static void mtd_check_of_node(struct mtd_info *mtd) > if (!mtd_is_partition(mtd)) > return; > parent = mtd->parent; > - parent_dn = dev_of_node(&parent->dev); > + parent_dn = of_node_get(dev_of_node(&parent->dev)); > if (!parent_dn) > return; Yes, with of_node_get() the refcount issue gone. > >