linux/drivers/of/overlay.c
<<
>>
Prefs
   1/*
   2 * Functions for working with device tree overlays
   3 *
   4 * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
   5 * Copyright (C) 2012 Texas Instruments Inc.
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License
   9 * version 2 as published by the Free Software Foundation.
  10 */
  11#undef DEBUG
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/of.h>
  15#include <linux/of_device.h>
  16#include <linux/string.h>
  17#include <linux/ctype.h>
  18#include <linux/errno.h>
  19#include <linux/string.h>
  20#include <linux/slab.h>
  21#include <linux/err.h>
  22#include <linux/idr.h>
  23
  24#include "of_private.h"
  25
  26/**
  27 * struct of_overlay_info - Holds a single overlay info
  28 * @target:     target of the overlay operation
  29 * @overlay:    pointer to the overlay contents node
  30 *
  31 * Holds a single overlay state, including all the overlay logs &
  32 * records.
  33 */
  34struct of_overlay_info {
  35        struct device_node *target;
  36        struct device_node *overlay;
  37};
  38
  39/**
  40 * struct of_overlay - Holds a complete overlay transaction
  41 * @node:       List on which we are located
  42 * @count:      Count of ovinfo structures
  43 * @ovinfo_tab: Overlay info table (count sized)
  44 * @cset:       Changeset to be used
  45 *
  46 * Holds a complete overlay transaction
  47 */
  48struct of_overlay {
  49        int id;
  50        struct list_head node;
  51        int count;
  52        struct of_overlay_info *ovinfo_tab;
  53        struct of_changeset cset;
  54};
  55
  56static int of_overlay_apply_one(struct of_overlay *ov,
  57                struct device_node *target, const struct device_node *overlay);
  58
  59static int of_overlay_apply_single_property(struct of_overlay *ov,
  60                struct device_node *target, struct property *prop)
  61{
  62        struct property *propn, *tprop;
  63
  64        /* NOTE: Multiple changes of single properties not supported */
  65        tprop = of_find_property(target, prop->name, NULL);
  66
  67        /* special properties are not meant to be updated (silent NOP) */
  68        if (of_prop_cmp(prop->name, "name") == 0 ||
  69            of_prop_cmp(prop->name, "phandle") == 0 ||
  70            of_prop_cmp(prop->name, "linux,phandle") == 0)
  71                return 0;
  72
  73        propn = __of_prop_dup(prop, GFP_KERNEL);
  74        if (propn == NULL)
  75                return -ENOMEM;
  76
  77        /* not found? add */
  78        if (tprop == NULL)
  79                return of_changeset_add_property(&ov->cset, target, propn);
  80
  81        /* found? update */
  82        return of_changeset_update_property(&ov->cset, target, propn);
  83}
  84
  85static int of_overlay_apply_single_device_node(struct of_overlay *ov,
  86                struct device_node *target, struct device_node *child)
  87{
  88        const char *cname;
  89        struct device_node *tchild;
  90        int ret = 0;
  91
  92        cname = kbasename(child->full_name);
  93        if (cname == NULL)
  94                return -ENOMEM;
  95
  96        /* NOTE: Multiple mods of created nodes not supported */
  97        tchild = of_get_child_by_name(target, cname);
  98        if (tchild != NULL) {
  99                /* apply overlay recursively */
 100                ret = of_overlay_apply_one(ov, tchild, child);
 101                of_node_put(tchild);
 102        } else {
 103                /* create empty tree as a target */
 104                tchild = __of_node_dup(child, "%s/%s", target->full_name, cname);
 105                if (!tchild)
 106                        return -ENOMEM;
 107
 108                /* point to parent */
 109                tchild->parent = target;
 110
 111                ret = of_changeset_attach_node(&ov->cset, tchild);
 112                if (ret)
 113                        return ret;
 114
 115                ret = of_overlay_apply_one(ov, tchild, child);
 116                if (ret)
 117                        return ret;
 118        }
 119
 120        return ret;
 121}
 122
 123/*
 124 * Apply a single overlay node recursively.
 125 *
 126 * Note that the in case of an error the target node is left
 127 * in a inconsistent state. Error recovery should be performed
 128 * by using the changeset.
 129 */
 130static int of_overlay_apply_one(struct of_overlay *ov,
 131                struct device_node *target, const struct device_node *overlay)
 132{
 133        struct device_node *child;
 134        struct property *prop;
 135        int ret;
 136
 137        for_each_property_of_node(overlay, prop) {
 138                ret = of_overlay_apply_single_property(ov, target, prop);
 139                if (ret) {
 140                        pr_err("%s: Failed to apply prop @%s/%s\n",
 141                                __func__, target->full_name, prop->name);
 142                        return ret;
 143                }
 144        }
 145
 146        for_each_child_of_node(overlay, child) {
 147                ret = of_overlay_apply_single_device_node(ov, target, child);
 148                if (ret != 0) {
 149                        pr_err("%s: Failed to apply single node @%s/%s\n",
 150                                        __func__, target->full_name,
 151                                        child->name);
 152                        return ret;
 153                }
 154        }
 155
 156        return 0;
 157}
 158
 159/**
 160 * of_overlay_apply() - Apply @count overlays pointed at by @ovinfo_tab
 161 * @ov:         Overlay to apply
 162 *
 163 * Applies the overlays given, while handling all error conditions
 164 * appropriately. Either the operation succeeds, or if it fails the
 165 * live tree is reverted to the state before the attempt.
 166 * Returns 0, or an error if the overlay attempt failed.
 167 */
 168static int of_overlay_apply(struct of_overlay *ov)
 169{
 170        int i, err;
 171
 172        /* first we apply the overlays atomically */
 173        for (i = 0; i < ov->count; i++) {
 174                struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i];
 175
 176                err = of_overlay_apply_one(ov, ovinfo->target, ovinfo->overlay);
 177                if (err != 0) {
 178                        pr_err("%s: overlay failed '%s'\n",
 179                                __func__, ovinfo->target->full_name);
 180                        return err;
 181                }
 182        }
 183
 184        return 0;
 185}
 186
 187/*
 188 * Find the target node using a number of different strategies
 189 * in order of preference
 190 *
 191 * "target" property containing the phandle of the target
 192 * "target-path" property containing the path of the target
 193 */
 194static struct device_node *find_target_node(struct device_node *info_node)
 195{
 196        const char *path;
 197        u32 val;
 198        int ret;
 199
 200        /* first try to go by using the target as a phandle */
 201        ret = of_property_read_u32(info_node, "target", &val);
 202        if (ret == 0)
 203                return of_find_node_by_phandle(val);
 204
 205        /* now try to locate by path */
 206        ret = of_property_read_string(info_node, "target-path", &path);
 207        if (ret == 0)
 208                return of_find_node_by_path(path);
 209
 210        pr_err("%s: Failed to find target for node %p (%s)\n", __func__,
 211                info_node, info_node->name);
 212
 213        return NULL;
 214}
 215
 216/**
 217 * of_fill_overlay_info() - Fill an overlay info structure
 218 * @ov          Overlay to fill
 219 * @info_node:  Device node containing the overlay
 220 * @ovinfo:     Pointer to the overlay info structure to fill
 221 *
 222 * Fills an overlay info structure with the overlay information
 223 * from a device node. This device node must have a target property
 224 * which contains a phandle of the overlay target node, and an
 225 * __overlay__ child node which has the overlay contents.
 226 * Both ovinfo->target & ovinfo->overlay have their references taken.
 227 *
 228 * Returns 0 on success, or a negative error value.
 229 */
 230static int of_fill_overlay_info(struct of_overlay *ov,
 231                struct device_node *info_node, struct of_overlay_info *ovinfo)
 232{
 233        ovinfo->overlay = of_get_child_by_name(info_node, "__overlay__");
 234        if (ovinfo->overlay == NULL)
 235                goto err_fail;
 236
 237        ovinfo->target = find_target_node(info_node);
 238        if (ovinfo->target == NULL)
 239                goto err_fail;
 240
 241        return 0;
 242
 243err_fail:
 244        of_node_put(ovinfo->target);
 245        of_node_put(ovinfo->overlay);
 246
 247        memset(ovinfo, 0, sizeof(*ovinfo));
 248        return -EINVAL;
 249}
 250
 251/**
 252 * of_build_overlay_info() - Build an overlay info array
 253 * @ov          Overlay to build
 254 * @tree:       Device node containing all the overlays
 255 *
 256 * Helper function that given a tree containing overlay information,
 257 * allocates and builds an overlay info array containing it, ready
 258 * for use using of_overlay_apply.
 259 *
 260 * Returns 0 on success with the @cntp @ovinfop pointers valid,
 261 * while on error a negative error value is returned.
 262 */
 263static int of_build_overlay_info(struct of_overlay *ov,
 264                struct device_node *tree)
 265{
 266        struct device_node *node;
 267        struct of_overlay_info *ovinfo;
 268        int cnt, err;
 269
 270        /* worst case; every child is a node */
 271        cnt = 0;
 272        for_each_child_of_node(tree, node)
 273                cnt++;
 274
 275        ovinfo = kcalloc(cnt, sizeof(*ovinfo), GFP_KERNEL);
 276        if (ovinfo == NULL)
 277                return -ENOMEM;
 278
 279        cnt = 0;
 280        for_each_child_of_node(tree, node) {
 281                memset(&ovinfo[cnt], 0, sizeof(*ovinfo));
 282                err = of_fill_overlay_info(ov, node, &ovinfo[cnt]);
 283                if (err == 0)
 284                        cnt++;
 285        }
 286
 287        /* if nothing filled, return error */
 288        if (cnt == 0) {
 289                kfree(ovinfo);
 290                return -ENODEV;
 291        }
 292
 293        ov->count = cnt;
 294        ov->ovinfo_tab = ovinfo;
 295
 296        return 0;
 297}
 298
 299/**
 300 * of_free_overlay_info() - Free an overlay info array
 301 * @ov          Overlay to free the overlay info from
 302 * @ovinfo_tab: Array of overlay_info's to free
 303 *
 304 * Releases the memory of a previously allocated ovinfo array
 305 * by of_build_overlay_info.
 306 * Returns 0, or an error if the arguments are bogus.
 307 */
 308static int of_free_overlay_info(struct of_overlay *ov)
 309{
 310        struct of_overlay_info *ovinfo;
 311        int i;
 312
 313        /* do it in reverse */
 314        for (i = ov->count - 1; i >= 0; i--) {
 315                ovinfo = &ov->ovinfo_tab[i];
 316
 317                of_node_put(ovinfo->target);
 318                of_node_put(ovinfo->overlay);
 319        }
 320        kfree(ov->ovinfo_tab);
 321
 322        return 0;
 323}
 324
 325static LIST_HEAD(ov_list);
 326static DEFINE_IDR(ov_idr);
 327
 328/**
 329 * of_overlay_create() - Create and apply an overlay
 330 * @tree:       Device node containing all the overlays
 331 *
 332 * Creates and applies an overlay while also keeping track
 333 * of the overlay in a list. This list can be used to prevent
 334 * illegal overlay removals.
 335 *
 336 * Returns the id of the created overlay, or a negative error number
 337 */
 338int of_overlay_create(struct device_node *tree)
 339{
 340        struct of_overlay *ov;
 341        int err, id;
 342
 343        /* allocate the overlay structure */
 344        ov = kzalloc(sizeof(*ov), GFP_KERNEL);
 345        if (ov == NULL)
 346                return -ENOMEM;
 347        ov->id = -1;
 348
 349        INIT_LIST_HEAD(&ov->node);
 350
 351        of_changeset_init(&ov->cset);
 352
 353        mutex_lock(&of_mutex);
 354
 355        id = idr_alloc(&ov_idr, ov, 0, 0, GFP_KERNEL);
 356        if (id < 0) {
 357                pr_err("%s: idr_alloc() failed for tree@%s\n",
 358                                __func__, tree->full_name);
 359                err = id;
 360                goto err_destroy_trans;
 361        }
 362        ov->id = id;
 363
 364        /* build the overlay info structures */
 365        err = of_build_overlay_info(ov, tree);
 366        if (err) {
 367                pr_err("%s: of_build_overlay_info() failed for tree@%s\n",
 368                                __func__, tree->full_name);
 369                goto err_free_idr;
 370        }
 371
 372        /* apply the overlay */
 373        err = of_overlay_apply(ov);
 374        if (err) {
 375                pr_err("%s: of_overlay_apply() failed for tree@%s\n",
 376                                __func__, tree->full_name);
 377                goto err_abort_trans;
 378        }
 379
 380        /* apply the changeset */
 381        err = of_changeset_apply(&ov->cset);
 382        if (err) {
 383                pr_err("%s: of_changeset_apply() failed for tree@%s\n",
 384                                __func__, tree->full_name);
 385                goto err_revert_overlay;
 386        }
 387
 388        /* add to the tail of the overlay list */
 389        list_add_tail(&ov->node, &ov_list);
 390
 391        mutex_unlock(&of_mutex);
 392
 393        return id;
 394
 395err_revert_overlay:
 396err_abort_trans:
 397        of_free_overlay_info(ov);
 398err_free_idr:
 399        idr_remove(&ov_idr, ov->id);
 400err_destroy_trans:
 401        of_changeset_destroy(&ov->cset);
 402        kfree(ov);
 403        mutex_unlock(&of_mutex);
 404
 405        return err;
 406}
 407EXPORT_SYMBOL_GPL(of_overlay_create);
 408
 409/* check whether the given node, lies under the given tree */
 410static int overlay_subtree_check(struct device_node *tree,
 411                struct device_node *dn)
 412{
 413        struct device_node *child;
 414
 415        /* match? */
 416        if (tree == dn)
 417                return 1;
 418
 419        for_each_child_of_node(tree, child) {
 420                if (overlay_subtree_check(child, dn))
 421                        return 1;
 422        }
 423
 424        return 0;
 425}
 426
 427/* check whether this overlay is the topmost */
 428static int overlay_is_topmost(struct of_overlay *ov, struct device_node *dn)
 429{
 430        struct of_overlay *ovt;
 431        struct of_changeset_entry *ce;
 432
 433        list_for_each_entry_reverse(ovt, &ov_list, node) {
 434                /* if we hit ourselves, we're done */
 435                if (ovt == ov)
 436                        break;
 437
 438                /* check against each subtree affected by this overlay */
 439                list_for_each_entry(ce, &ovt->cset.entries, node) {
 440                        if (overlay_subtree_check(ce->np, dn)) {
 441                                pr_err("%s: #%d clashes #%d @%s\n",
 442                                        __func__, ov->id, ovt->id,
 443                                        dn->full_name);
 444                                return 0;
 445                        }
 446                }
 447        }
 448
 449        /* overlay is topmost */
 450        return 1;
 451}
 452
 453/*
 454 * We can safely remove the overlay only if it's the top-most one.
 455 * Newly applied overlays are inserted at the tail of the overlay list,
 456 * so a top most overlay is the one that is closest to the tail.
 457 *
 458 * The topmost check is done by exploiting this property. For each
 459 * affected device node in the log list we check if this overlay is
 460 * the one closest to the tail. If another overlay has affected this
 461 * device node and is closest to the tail, then removal is not permited.
 462 */
 463static int overlay_removal_is_ok(struct of_overlay *ov)
 464{
 465        struct of_changeset_entry *ce;
 466
 467        list_for_each_entry(ce, &ov->cset.entries, node) {
 468                if (!overlay_is_topmost(ov, ce->np)) {
 469                        pr_err("%s: overlay #%d is not topmost\n",
 470                                        __func__, ov->id);
 471                        return 0;
 472                }
 473        }
 474
 475        return 1;
 476}
 477
 478/**
 479 * of_overlay_destroy() - Removes an overlay
 480 * @id: Overlay id number returned by a previous call to of_overlay_create
 481 *
 482 * Removes an overlay if it is permissible.
 483 *
 484 * Returns 0 on success, or a negative error number
 485 */
 486int of_overlay_destroy(int id)
 487{
 488        struct of_overlay *ov;
 489        int err;
 490
 491        mutex_lock(&of_mutex);
 492
 493        ov = idr_find(&ov_idr, id);
 494        if (ov == NULL) {
 495                err = -ENODEV;
 496                pr_err("%s: Could not find overlay #%d\n",
 497                                __func__, id);
 498                goto out;
 499        }
 500
 501        /* check whether the overlay is safe to remove */
 502        if (!overlay_removal_is_ok(ov)) {
 503                err = -EBUSY;
 504                pr_err("%s: removal check failed for overlay #%d\n",
 505                                __func__, id);
 506                goto out;
 507        }
 508
 509
 510        list_del(&ov->node);
 511        of_changeset_revert(&ov->cset);
 512        of_free_overlay_info(ov);
 513        idr_remove(&ov_idr, id);
 514        of_changeset_destroy(&ov->cset);
 515        kfree(ov);
 516
 517        err = 0;
 518
 519out:
 520        mutex_unlock(&of_mutex);
 521
 522        return err;
 523}
 524EXPORT_SYMBOL_GPL(of_overlay_destroy);
 525
 526/**
 527 * of_overlay_destroy_all() - Removes all overlays from the system
 528 *
 529 * Removes all overlays from the system in the correct order.
 530 *
 531 * Returns 0 on success, or a negative error number
 532 */
 533int of_overlay_destroy_all(void)
 534{
 535        struct of_overlay *ov, *ovn;
 536
 537        mutex_lock(&of_mutex);
 538
 539        /* the tail of list is guaranteed to be safe to remove */
 540        list_for_each_entry_safe_reverse(ov, ovn, &ov_list, node) {
 541                list_del(&ov->node);
 542                of_changeset_revert(&ov->cset);
 543                of_free_overlay_info(ov);
 544                idr_remove(&ov_idr, ov->id);
 545                kfree(ov);
 546        }
 547
 548        mutex_unlock(&of_mutex);
 549
 550        return 0;
 551}
 552EXPORT_SYMBOL_GPL(of_overlay_destroy_all);
 553