linux/drivers/acpi/acpica/nsutils.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
   5 *                        parents and siblings and Scope manipulation
   6 *
   7 * Copyright (C) 2000 - 2021, Intel Corp.
   8 *
   9 *****************************************************************************/
  10
  11#include <acpi/acpi.h>
  12#include "accommon.h"
  13#include "acnamesp.h"
  14#include "amlcode.h"
  15
  16#define _COMPONENT          ACPI_NAMESPACE
  17ACPI_MODULE_NAME("nsutils")
  18
  19/* Local prototypes */
  20#ifdef ACPI_OBSOLETE_FUNCTIONS
  21acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
  22#endif
  23
  24/*******************************************************************************
  25 *
  26 * FUNCTION:    acpi_ns_print_node_pathname
  27 *
  28 * PARAMETERS:  node            - Object
  29 *              message         - Prefix message
  30 *
  31 * DESCRIPTION: Print an object's full namespace pathname
  32 *              Manages allocation/freeing of a pathname buffer
  33 *
  34 ******************************************************************************/
  35
  36void
  37acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
  38                            const char *message)
  39{
  40        struct acpi_buffer buffer;
  41        acpi_status status;
  42
  43        if (!node) {
  44                acpi_os_printf("[NULL NAME]");
  45                return;
  46        }
  47
  48        /* Convert handle to full pathname and print it (with supplied message) */
  49
  50        buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
  51
  52        status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
  53        if (ACPI_SUCCESS(status)) {
  54                if (message) {
  55                        acpi_os_printf("%s ", message);
  56                }
  57
  58                acpi_os_printf("%s", (char *)buffer.pointer);
  59                ACPI_FREE(buffer.pointer);
  60        }
  61}
  62
  63/*******************************************************************************
  64 *
  65 * FUNCTION:    acpi_ns_get_type
  66 *
  67 * PARAMETERS:  node        - Parent Node to be examined
  68 *
  69 * RETURN:      Type field from Node whose handle is passed
  70 *
  71 * DESCRIPTION: Return the type of a Namespace node
  72 *
  73 ******************************************************************************/
  74
  75acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
  76{
  77        ACPI_FUNCTION_TRACE(ns_get_type);
  78
  79        if (!node) {
  80                ACPI_WARNING((AE_INFO, "Null Node parameter"));
  81                return_UINT8(ACPI_TYPE_ANY);
  82        }
  83
  84        return_UINT8(node->type);
  85}
  86
  87/*******************************************************************************
  88 *
  89 * FUNCTION:    acpi_ns_local
  90 *
  91 * PARAMETERS:  type        - A namespace object type
  92 *
  93 * RETURN:      LOCAL if names must be found locally in objects of the
  94 *              passed type, 0 if enclosing scopes should be searched
  95 *
  96 * DESCRIPTION: Returns scope rule for the given object type.
  97 *
  98 ******************************************************************************/
  99
 100u32 acpi_ns_local(acpi_object_type type)
 101{
 102        ACPI_FUNCTION_TRACE(ns_local);
 103
 104        if (!acpi_ut_valid_object_type(type)) {
 105
 106                /* Type code out of range  */
 107
 108                ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
 109                return_UINT32(ACPI_NS_NORMAL);
 110        }
 111
 112        return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
 113}
 114
 115/*******************************************************************************
 116 *
 117 * FUNCTION:    acpi_ns_get_internal_name_length
 118 *
 119 * PARAMETERS:  info            - Info struct initialized with the
 120 *                                external name pointer.
 121 *
 122 * RETURN:      None
 123 *
 124 * DESCRIPTION: Calculate the length of the internal (AML) namestring
 125 *              corresponding to the external (ASL) namestring.
 126 *
 127 ******************************************************************************/
 128
 129void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
 130{
 131        const char *next_external_char;
 132        u32 i;
 133
 134        ACPI_FUNCTION_ENTRY();
 135
 136        next_external_char = info->external_name;
 137        info->num_carats = 0;
 138        info->num_segments = 0;
 139        info->fully_qualified = FALSE;
 140
 141        /*
 142         * For the internal name, the required length is 4 bytes per segment,
 143         * plus 1 each for root_prefix, multi_name_prefix_op, segment count,
 144         * trailing null (which is not really needed, but no there's harm in
 145         * putting it there)
 146         *
 147         * strlen() + 1 covers the first name_seg, which has no path separator
 148         */
 149        if (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
 150                info->fully_qualified = TRUE;
 151                next_external_char++;
 152
 153                /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */
 154
 155                while (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
 156                        next_external_char++;
 157                }
 158        } else {
 159                /* Handle Carat prefixes */
 160
 161                while (ACPI_IS_PARENT_PREFIX(*next_external_char)) {
 162                        info->num_carats++;
 163                        next_external_char++;
 164                }
 165        }
 166
 167        /*
 168         * Determine the number of ACPI name "segments" by counting the number of
 169         * path separators within the string. Start with one segment since the
 170         * segment count is [(# separators) + 1], and zero separators is ok.
 171         */
 172        if (*next_external_char) {
 173                info->num_segments = 1;
 174                for (i = 0; next_external_char[i]; i++) {
 175                        if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) {
 176                                info->num_segments++;
 177                        }
 178                }
 179        }
 180
 181        info->length = (ACPI_NAMESEG_SIZE * info->num_segments) +
 182            4 + info->num_carats;
 183
 184        info->next_external_char = next_external_char;
 185}
 186
 187/*******************************************************************************
 188 *
 189 * FUNCTION:    acpi_ns_build_internal_name
 190 *
 191 * PARAMETERS:  info            - Info struct fully initialized
 192 *
 193 * RETURN:      Status
 194 *
 195 * DESCRIPTION: Construct the internal (AML) namestring
 196 *              corresponding to the external (ASL) namestring.
 197 *
 198 ******************************************************************************/
 199
 200acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
 201{
 202        u32 num_segments = info->num_segments;
 203        char *internal_name = info->internal_name;
 204        const char *external_name = info->next_external_char;
 205        char *result = NULL;
 206        u32 i;
 207
 208        ACPI_FUNCTION_TRACE(ns_build_internal_name);
 209
 210        /* Setup the correct prefixes, counts, and pointers */
 211
 212        if (info->fully_qualified) {
 213                internal_name[0] = AML_ROOT_PREFIX;
 214
 215                if (num_segments <= 1) {
 216                        result = &internal_name[1];
 217                } else if (num_segments == 2) {
 218                        internal_name[1] = AML_DUAL_NAME_PREFIX;
 219                        result = &internal_name[2];
 220                } else {
 221                        internal_name[1] = AML_MULTI_NAME_PREFIX;
 222                        internal_name[2] = (char)num_segments;
 223                        result = &internal_name[3];
 224                }
 225        } else {
 226                /*
 227                 * Not fully qualified.
 228                 * Handle Carats first, then append the name segments
 229                 */
 230                i = 0;
 231                if (info->num_carats) {
 232                        for (i = 0; i < info->num_carats; i++) {
 233                                internal_name[i] = AML_PARENT_PREFIX;
 234                        }
 235                }
 236
 237                if (num_segments <= 1) {
 238                        result = &internal_name[i];
 239                } else if (num_segments == 2) {
 240                        internal_name[i] = AML_DUAL_NAME_PREFIX;
 241                        result = &internal_name[(acpi_size)i + 1];
 242                } else {
 243                        internal_name[i] = AML_MULTI_NAME_PREFIX;
 244                        internal_name[(acpi_size)i + 1] = (char)num_segments;
 245                        result = &internal_name[(acpi_size)i + 2];
 246                }
 247        }
 248
 249        /* Build the name (minus path separators) */
 250
 251        for (; num_segments; num_segments--) {
 252                for (i = 0; i < ACPI_NAMESEG_SIZE; i++) {
 253                        if (ACPI_IS_PATH_SEPARATOR(*external_name) ||
 254                            (*external_name == 0)) {
 255
 256                                /* Pad the segment with underscore(s) if segment is short */
 257
 258                                result[i] = '_';
 259                        } else {
 260                                /* Convert the character to uppercase and save it */
 261
 262                                result[i] = (char)toupper((int)*external_name);
 263                                external_name++;
 264                        }
 265                }
 266
 267                /* Now we must have a path separator, or the pathname is bad */
 268
 269                if (!ACPI_IS_PATH_SEPARATOR(*external_name) &&
 270                    (*external_name != 0)) {
 271                        return_ACPI_STATUS(AE_BAD_PATHNAME);
 272                }
 273
 274                /* Move on the next segment */
 275
 276                external_name++;
 277                result += ACPI_NAMESEG_SIZE;
 278        }
 279
 280        /* Terminate the string */
 281
 282        *result = 0;
 283
 284        if (info->fully_qualified) {
 285                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 286                                  "Returning [%p] (abs) \"\\%s\"\n",
 287                                  internal_name, internal_name));
 288        } else {
 289                ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
 290                                  internal_name, internal_name));
 291        }
 292
 293        return_ACPI_STATUS(AE_OK);
 294}
 295
 296/*******************************************************************************
 297 *
 298 * FUNCTION:    acpi_ns_internalize_name
 299 *
 300 * PARAMETERS:  *external_name          - External representation of name
 301 *              **Converted name        - Where to return the resulting
 302 *                                        internal represention of the name
 303 *
 304 * RETURN:      Status
 305 *
 306 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
 307 *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
 308 *
 309 *******************************************************************************/
 310
 311acpi_status
 312acpi_ns_internalize_name(const char *external_name, char **converted_name)
 313{
 314        char *internal_name;
 315        struct acpi_namestring_info info;
 316        acpi_status status;
 317
 318        ACPI_FUNCTION_TRACE(ns_internalize_name);
 319
 320        if ((!external_name) || (*external_name == 0) || (!converted_name)) {
 321                return_ACPI_STATUS(AE_BAD_PARAMETER);
 322        }
 323
 324        /* Get the length of the new internal name */
 325
 326        info.external_name = external_name;
 327        acpi_ns_get_internal_name_length(&info);
 328
 329        /* We need a segment to store the internal  name */
 330
 331        internal_name = ACPI_ALLOCATE_ZEROED(info.length);
 332        if (!internal_name) {
 333                return_ACPI_STATUS(AE_NO_MEMORY);
 334        }
 335
 336        /* Build the name */
 337
 338        info.internal_name = internal_name;
 339        status = acpi_ns_build_internal_name(&info);
 340        if (ACPI_FAILURE(status)) {
 341                ACPI_FREE(internal_name);
 342                return_ACPI_STATUS(status);
 343        }
 344
 345        *converted_name = internal_name;
 346        return_ACPI_STATUS(AE_OK);
 347}
 348
 349/*******************************************************************************
 350 *
 351 * FUNCTION:    acpi_ns_externalize_name
 352 *
 353 * PARAMETERS:  internal_name_length - Length of the internal name below
 354 *              internal_name       - Internal representation of name
 355 *              converted_name_length - Where the length is returned
 356 *              converted_name      - Where the resulting external name
 357 *                                    is returned
 358 *
 359 * RETURN:      Status
 360 *
 361 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
 362 *              to its external (printable) form (e.g. "\_PR_.CPU0")
 363 *
 364 ******************************************************************************/
 365
 366acpi_status
 367acpi_ns_externalize_name(u32 internal_name_length,
 368                         const char *internal_name,
 369                         u32 * converted_name_length, char **converted_name)
 370{
 371        u32 names_index = 0;
 372        u32 num_segments = 0;
 373        u32 required_length;
 374        u32 prefix_length = 0;
 375        u32 i = 0;
 376        u32 j = 0;
 377
 378        ACPI_FUNCTION_TRACE(ns_externalize_name);
 379
 380        if (!internal_name_length || !internal_name || !converted_name) {
 381                return_ACPI_STATUS(AE_BAD_PARAMETER);
 382        }
 383
 384        /* Check for a prefix (one '\' | one or more '^') */
 385
 386        switch (internal_name[0]) {
 387        case AML_ROOT_PREFIX:
 388
 389                prefix_length = 1;
 390                break;
 391
 392        case AML_PARENT_PREFIX:
 393
 394                for (i = 0; i < internal_name_length; i++) {
 395                        if (ACPI_IS_PARENT_PREFIX(internal_name[i])) {
 396                                prefix_length = i + 1;
 397                        } else {
 398                                break;
 399                        }
 400                }
 401
 402                if (i == internal_name_length) {
 403                        prefix_length = i;
 404                }
 405
 406                break;
 407
 408        default:
 409
 410                break;
 411        }
 412
 413        /*
 414         * Check for object names. Note that there could be 0-255 of these
 415         * 4-byte elements.
 416         */
 417        if (prefix_length < internal_name_length) {
 418                switch (internal_name[prefix_length]) {
 419                case AML_MULTI_NAME_PREFIX:
 420
 421                        /* <count> 4-byte names */
 422
 423                        names_index = prefix_length + 2;
 424                        num_segments = (u8)
 425                            internal_name[(acpi_size)prefix_length + 1];
 426                        break;
 427
 428                case AML_DUAL_NAME_PREFIX:
 429
 430                        /* Two 4-byte names */
 431
 432                        names_index = prefix_length + 1;
 433                        num_segments = 2;
 434                        break;
 435
 436                case 0:
 437
 438                        /* null_name */
 439
 440                        names_index = 0;
 441                        num_segments = 0;
 442                        break;
 443
 444                default:
 445
 446                        /* one 4-byte name */
 447
 448                        names_index = prefix_length;
 449                        num_segments = 1;
 450                        break;
 451                }
 452        }
 453
 454        /*
 455         * Calculate the length of converted_name, which equals the length
 456         * of the prefix, length of all object names, length of any required
 457         * punctuation ('.') between object names, plus the NULL terminator.
 458         */
 459        required_length = prefix_length + (4 * num_segments) +
 460            ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
 461
 462        /*
 463         * Check to see if we're still in bounds. If not, there's a problem
 464         * with internal_name (invalid format).
 465         */
 466        if (required_length > internal_name_length) {
 467                ACPI_ERROR((AE_INFO, "Invalid internal name"));
 468                return_ACPI_STATUS(AE_BAD_PATHNAME);
 469        }
 470
 471        /* Build the converted_name */
 472
 473        *converted_name = ACPI_ALLOCATE_ZEROED(required_length);
 474        if (!(*converted_name)) {
 475                return_ACPI_STATUS(AE_NO_MEMORY);
 476        }
 477
 478        j = 0;
 479
 480        for (i = 0; i < prefix_length; i++) {
 481                (*converted_name)[j++] = internal_name[i];
 482        }
 483
 484        if (num_segments > 0) {
 485                for (i = 0; i < num_segments; i++) {
 486                        if (i > 0) {
 487                                (*converted_name)[j++] = '.';
 488                        }
 489
 490                        /* Copy and validate the 4-char name segment */
 491
 492                        ACPI_COPY_NAMESEG(&(*converted_name)[j],
 493                                          &internal_name[names_index]);
 494                        acpi_ut_repair_name(&(*converted_name)[j]);
 495
 496                        j += ACPI_NAMESEG_SIZE;
 497                        names_index += ACPI_NAMESEG_SIZE;
 498                }
 499        }
 500
 501        if (converted_name_length) {
 502                *converted_name_length = (u32) required_length;
 503        }
 504
 505        return_ACPI_STATUS(AE_OK);
 506}
 507
 508/*******************************************************************************
 509 *
 510 * FUNCTION:    acpi_ns_validate_handle
 511 *
 512 * PARAMETERS:  handle          - Handle to be validated and typecast to a
 513 *                                namespace node.
 514 *
 515 * RETURN:      A pointer to a namespace node
 516 *
 517 * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
 518 *              cases for the root node.
 519 *
 520 * NOTE: Real integer handles would allow for more verification
 521 *       and keep all pointers within this subsystem - however this introduces
 522 *       more overhead and has not been necessary to this point. Drivers
 523 *       holding handles are typically notified before a node becomes invalid
 524 *       due to a table unload.
 525 *
 526 ******************************************************************************/
 527
 528struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
 529{
 530
 531        ACPI_FUNCTION_ENTRY();
 532
 533        /* Parameter validation */
 534
 535        if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
 536                return (acpi_gbl_root_node);
 537        }
 538
 539        /* We can at least attempt to verify the handle */
 540
 541        if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
 542                return (NULL);
 543        }
 544
 545        return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
 546}
 547
 548/*******************************************************************************
 549 *
 550 * FUNCTION:    acpi_ns_terminate
 551 *
 552 * PARAMETERS:  none
 553 *
 554 * RETURN:      none
 555 *
 556 * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
 557 *
 558 ******************************************************************************/
 559
 560void acpi_ns_terminate(void)
 561{
 562        acpi_status status;
 563
 564        ACPI_FUNCTION_TRACE(ns_terminate);
 565
 566        /*
 567         * Free the entire namespace -- all nodes and all objects
 568         * attached to the nodes
 569         */
 570        acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
 571
 572        /* Delete any objects attached to the root node */
 573
 574        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 575        if (ACPI_FAILURE(status)) {
 576                return_VOID;
 577        }
 578
 579        acpi_ns_delete_node(acpi_gbl_root_node);
 580        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 581
 582        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
 583        return_VOID;
 584}
 585
 586/*******************************************************************************
 587 *
 588 * FUNCTION:    acpi_ns_opens_scope
 589 *
 590 * PARAMETERS:  type        - A valid namespace type
 591 *
 592 * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
 593 *              to the ACPI specification, else 0
 594 *
 595 ******************************************************************************/
 596
 597u32 acpi_ns_opens_scope(acpi_object_type type)
 598{
 599        ACPI_FUNCTION_ENTRY();
 600
 601        if (type > ACPI_TYPE_LOCAL_MAX) {
 602
 603                /* type code out of range  */
 604
 605                ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
 606                return (ACPI_NS_NORMAL);
 607        }
 608
 609        return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
 610}
 611
 612/*******************************************************************************
 613 *
 614 * FUNCTION:    acpi_ns_get_node_unlocked
 615 *
 616 * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
 617 *                            \ (backslash) and ^ (carat) prefixes, and the
 618 *                            . (period) to separate segments are supported.
 619 *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
 620 *                            root of the name space. If Name is fully
 621 *                            qualified (first s8 is '\'), the passed value
 622 *                            of Scope will not be accessed.
 623 *              flags       - Used to indicate whether to perform upsearch or
 624 *                            not.
 625 *              return_node - Where the Node is returned
 626 *
 627 * DESCRIPTION: Look up a name relative to a given scope and return the
 628 *              corresponding Node. NOTE: Scope can be null.
 629 *
 630 * MUTEX:       Doesn't locks namespace
 631 *
 632 ******************************************************************************/
 633
 634acpi_status
 635acpi_ns_get_node_unlocked(struct acpi_namespace_node *prefix_node,
 636                          const char *pathname,
 637                          u32 flags, struct acpi_namespace_node **return_node)
 638{
 639        union acpi_generic_state scope_info;
 640        acpi_status status;
 641        char *internal_path;
 642
 643        ACPI_FUNCTION_TRACE_PTR(ns_get_node_unlocked,
 644                                ACPI_CAST_PTR(char, pathname));
 645
 646        /* Simplest case is a null pathname */
 647
 648        if (!pathname) {
 649                *return_node = prefix_node;
 650                if (!prefix_node) {
 651                        *return_node = acpi_gbl_root_node;
 652                }
 653
 654                return_ACPI_STATUS(AE_OK);
 655        }
 656
 657        /* Quick check for a reference to the root */
 658
 659        if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) {
 660                *return_node = acpi_gbl_root_node;
 661                return_ACPI_STATUS(AE_OK);
 662        }
 663
 664        /* Convert path to internal representation */
 665
 666        status = acpi_ns_internalize_name(pathname, &internal_path);
 667        if (ACPI_FAILURE(status)) {
 668                return_ACPI_STATUS(status);
 669        }
 670
 671        /* Setup lookup scope (search starting point) */
 672
 673        scope_info.scope.node = prefix_node;
 674
 675        /* Lookup the name in the namespace */
 676
 677        status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
 678                                ACPI_IMODE_EXECUTE,
 679                                (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
 680                                return_node);
 681        if (ACPI_FAILURE(status)) {
 682                ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
 683                                  pathname, acpi_format_exception(status)));
 684        }
 685
 686        ACPI_FREE(internal_path);
 687        return_ACPI_STATUS(status);
 688}
 689
 690/*******************************************************************************
 691 *
 692 * FUNCTION:    acpi_ns_get_node
 693 *
 694 * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
 695 *                            \ (backslash) and ^ (carat) prefixes, and the
 696 *                            . (period) to separate segments are supported.
 697 *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
 698 *                            root of the name space. If Name is fully
 699 *                            qualified (first s8 is '\'), the passed value
 700 *                            of Scope will not be accessed.
 701 *              flags       - Used to indicate whether to perform upsearch or
 702 *                            not.
 703 *              return_node - Where the Node is returned
 704 *
 705 * DESCRIPTION: Look up a name relative to a given scope and return the
 706 *              corresponding Node. NOTE: Scope can be null.
 707 *
 708 * MUTEX:       Locks namespace
 709 *
 710 ******************************************************************************/
 711
 712acpi_status
 713acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
 714                 const char *pathname,
 715                 u32 flags, struct acpi_namespace_node **return_node)
 716{
 717        acpi_status status;
 718
 719        ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
 720
 721        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 722        if (ACPI_FAILURE(status)) {
 723                return_ACPI_STATUS(status);
 724        }
 725
 726        status = acpi_ns_get_node_unlocked(prefix_node, pathname,
 727                                           flags, return_node);
 728
 729        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 730        return_ACPI_STATUS(status);
 731}
 732