USB: fix locking in idmouse
[safe/jmp/linux-2.6] / drivers / acpi / hardware / hwregs.c
index b243f20..73f9c5f 100644 (file)
@@ -7,7 +7,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2007, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,8 +43,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
@@ -56,33 +54,28 @@ ACPI_MODULE_NAME("hwregs")
  *
  * FUNCTION:    acpi_hw_clear_acpi_status
  *
- * PARAMETERS:  Flags           - Lock the hardware or not
+ * PARAMETERS:  None
  *
- * RETURN:      none
+ * RETURN:      None
  *
  * DESCRIPTION: Clears all fixed and general purpose status bits
  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
-acpi_status acpi_hw_clear_acpi_status(u32 flags)
+acpi_status acpi_hw_clear_acpi_status(void)
 {
        acpi_status status;
+       acpi_cpu_flags lock_flags = 0;
 
-       ACPI_FUNCTION_TRACE("hw_clear_acpi_status");
+       ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
 
        ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
                          ACPI_BITMASK_ALL_FIXED_STATUS,
-                         (u16) acpi_gbl_FADT->xpm1a_evt_blk.address));
+                         (u16) acpi_gbl_FADT.xpm1a_event_block.address));
 
-       if (flags & ACPI_MTX_LOCK) {
-               status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
-               if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
-               }
-       }
+       lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
 
-       status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
-                                       ACPI_REGISTER_PM1_STATUS,
+       status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
                                        ACPI_BITMASK_ALL_FIXED_STATUS);
        if (ACPI_FAILURE(status)) {
                goto unlock_and_exit;
@@ -90,10 +83,10 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags)
 
        /* Clear the fixed events */
 
-       if (acpi_gbl_FADT->xpm1b_evt_blk.address) {
+       if (acpi_gbl_FADT.xpm1b_event_block.address) {
                status =
                    acpi_hw_low_level_write(16, ACPI_BITMASK_ALL_FIXED_STATUS,
-                                           &acpi_gbl_FADT->xpm1b_evt_blk);
+                                           &acpi_gbl_FADT.xpm1b_event_block);
                if (ACPI_FAILURE(status)) {
                        goto unlock_and_exit;
                }
@@ -104,9 +97,7 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags)
        status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
 
       unlock_and_exit:
-       if (flags & ACPI_MTX_LOCK) {
-               (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
-       }
+       acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
        return_ACPI_STATUS(status);
 }
 
@@ -129,10 +120,9 @@ acpi_status
 acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
 {
        acpi_status status = AE_OK;
-       struct acpi_parameter_info info;
-       char *sleep_state_name;
+       struct acpi_evaluate_info *info;
 
-       ACPI_FUNCTION_TRACE("acpi_get_sleep_type_data");
+       ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data);
 
        /* Validate parameters */
 
@@ -140,81 +130,95 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
-       /* Evaluate the namespace object containing the values for this state */
+       /* Allocate the evaluation information block */
+
+       info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+       if (!info) {
+               return_ACPI_STATUS(AE_NO_MEMORY);
+       }
 
-       info.parameters = NULL;
-       info.return_object = NULL;
-       sleep_state_name =
+       info->pathname =
            ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
 
-       status = acpi_ns_evaluate_by_name(sleep_state_name, &info);
+       /* Evaluate the namespace object containing the values for this state */
+
+       status = acpi_ns_evaluate(info);
        if (ACPI_FAILURE(status)) {
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-                                 "%s while evaluating sleep_state [%s]\n",
+                                 "%s while evaluating SleepState [%s]\n",
                                  acpi_format_exception(status),
-                                 sleep_state_name));
+                                 info->pathname));
 
-               return_ACPI_STATUS(status);
+               goto cleanup;
        }
 
        /* Must have a return object */
 
-       if (!info.return_object) {
-               ACPI_REPORT_ERROR(("No Sleep State object returned from [%s]\n",
-                                  sleep_state_name));
+       if (!info->return_object) {
+               ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
+                           info->pathname));
                status = AE_NOT_EXIST;
        }
 
        /* It must be of type Package */
 
-       else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) {
-               ACPI_REPORT_ERROR(("Sleep State return object is not a Package\n"));
+       else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) {
+               ACPI_ERROR((AE_INFO,
+                           "Sleep State return object is not a Package"));
                status = AE_AML_OPERAND_TYPE;
        }
 
        /*
-        * The package must have at least two elements.  NOTE (March 2005): This
+        * The package must have at least two elements. NOTE (March 2005): This
         * goes against the current ACPI spec which defines this object as a
-        * package with one encoded DWORD element.  However, existing practice
+        * package with one encoded DWORD element. However, existing practice
         * by BIOS vendors seems to be to have 2 or more elements, at least
         * one per sleep type (A/B).
         */
-       else if (info.return_object->package.count < 2) {
-               ACPI_REPORT_ERROR(("Sleep State return package does not have at least two elements\n"));
+       else if (info->return_object->package.count < 2) {
+               ACPI_ERROR((AE_INFO,
+                           "Sleep State return package does not have at least two elements"));
                status = AE_AML_NO_OPERAND;
        }
 
        /* The first two elements must both be of type Integer */
 
-       else if ((ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[0])
+       else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0])
                  != ACPI_TYPE_INTEGER) ||
-                (ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[1])
+                (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1])
                  != ACPI_TYPE_INTEGER)) {
-               ACPI_REPORT_ERROR(("Sleep State return package elements are not both Integers (%s, %s)\n", acpi_ut_get_object_type_name(info.return_object->package.elements[0]), acpi_ut_get_object_type_name(info.return_object->package.elements[1])));
+               ACPI_ERROR((AE_INFO,
+                           "Sleep State return package elements are not both Integers (%s, %s)",
+                           acpi_ut_get_object_type_name(info->return_object->
+                                                        package.elements[0]),
+                           acpi_ut_get_object_type_name(info->return_object->
+                                                        package.elements[1])));
                status = AE_AML_OPERAND_TYPE;
        } else {
                /* Valid _Sx_ package size, type, and value */
 
                *sleep_type_a = (u8)
-                   (info.return_object->package.elements[0])->integer.value;
+                   (info->return_object->package.elements[0])->integer.value;
                *sleep_type_b = (u8)
-                   (info.return_object->package.elements[1])->integer.value;
+                   (info->return_object->package.elements[1])->integer.value;
        }
 
        if (ACPI_FAILURE(status)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "%s While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
-                                 acpi_format_exception(status),
-                                 sleep_state_name, info.return_object,
-                                 acpi_ut_get_object_type_name(info.
-                                                              return_object)));
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "While evaluating SleepState [%s], bad Sleep object %p type %s",
+                               info->pathname, info->return_object,
+                               acpi_ut_get_object_type_name(info->
+                                                            return_object)));
        }
 
-       acpi_ut_remove_reference(info.return_object);
+       acpi_ut_remove_reference(info->return_object);
+
+      cleanup:
+       ACPI_FREE(info);
        return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_sleep_type_data);
+ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data)
 
 /*******************************************************************************
  *
@@ -227,15 +231,13 @@ EXPORT_SYMBOL(acpi_get_sleep_type_data);
  * DESCRIPTION: Map register_id into a register bitmask.
  *
  ******************************************************************************/
-
 struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
 {
-       ACPI_FUNCTION_NAME("hw_get_bit_register_info");
+       ACPI_FUNCTION_ENTRY();
 
        if (register_id > ACPI_BITREG_MAX) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Invalid bit_register ID: %X\n",
-                                 register_id));
+               ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X",
+                           register_id));
                return (NULL);
        }
 
@@ -248,22 +250,21 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
  *
  * PARAMETERS:  register_id     - ID of ACPI bit_register to access
  *              return_value    - Value that was read from the register
- *              Flags           - Lock the hardware or not
  *
- * RETURN:      Status and the value read from specified Register.  Value
+ * RETURN:      Status and the value read from specified Register. Value
  *              returned is normalized to bit0 (is shifted all the way right)
  *
  * DESCRIPTION: ACPI bit_register read function.
  *
  ******************************************************************************/
 
-acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
+acpi_status acpi_get_register_unlocked(u32 register_id, u32 * return_value)
 {
        u32 register_value = 0;
        struct acpi_bit_register_info *bit_reg_info;
        acpi_status status;
 
-       ACPI_FUNCTION_TRACE("acpi_get_register");
+       ACPI_FUNCTION_TRACE(acpi_get_register);
 
        /* Get the info structure corresponding to the requested ACPI Register */
 
@@ -272,24 +273,13 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
-       if (flags & ACPI_MTX_LOCK) {
-               status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
-               if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
-               }
-       }
-
        /* Read from the register */
 
-       status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
-                                      bit_reg_info->parent_register,
+       status = acpi_hw_register_read(bit_reg_info->parent_register,
                                       &register_value);
 
-       if (flags & ACPI_MTX_LOCK) {
-               (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
-       }
-
        if (ACPI_SUCCESS(status)) {
+
                /* Normalize the value that was read */
 
                register_value =
@@ -306,7 +296,17 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
        return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_register);
+acpi_status acpi_get_register(u32 register_id, u32 * return_value)
+{
+       acpi_status status;
+       acpi_cpu_flags flags;
+       flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
+       status = acpi_get_register_unlocked(register_id, return_value);
+       acpi_os_release_lock(acpi_gbl_hardware_lock, flags);
+       return status;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_register)
 
 /*******************************************************************************
  *
@@ -315,42 +315,35 @@ EXPORT_SYMBOL(acpi_get_register);
  * PARAMETERS:  register_id     - ID of ACPI bit_register to access
  *              Value           - (only used on write) value to write to the
  *                                Register, NOT pre-normalized to the bit pos
- *              Flags           - Lock the hardware or not
  *
  * RETURN:      Status
  *
  * DESCRIPTION: ACPI Bit Register write function.
  *
  ******************************************************************************/
-
-acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
+acpi_status acpi_set_register(u32 register_id, u32 value)
 {
        u32 register_value = 0;
        struct acpi_bit_register_info *bit_reg_info;
        acpi_status status;
+       acpi_cpu_flags lock_flags;
 
-       ACPI_FUNCTION_TRACE_U32("acpi_set_register", register_id);
+       ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id);
 
        /* Get the info structure corresponding to the requested ACPI Register */
 
        bit_reg_info = acpi_hw_get_bit_register_info(register_id);
        if (!bit_reg_info) {
-               ACPI_REPORT_ERROR(("Bad ACPI HW register_id: %X\n",
-                                  register_id));
+               ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X",
+                           register_id));
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
-       if (flags & ACPI_MTX_LOCK) {
-               status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
-               if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
-               }
-       }
+       lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
 
        /* Always do a register read first so we can insert the new bits  */
 
-       status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
-                                      bit_reg_info->parent_register,
+       status = acpi_hw_register_read(bit_reg_info->parent_register,
                                       &register_value);
        if (ACPI_FAILURE(status)) {
                goto unlock_and_exit;
@@ -367,8 +360,8 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
        case ACPI_REGISTER_PM1_STATUS:
 
                /*
-                * Status Registers are different from the rest.  Clear by
-                * writing 1, and writing 0 has no effect.  So, the only relevant
+                * Status Registers are different from the rest. Clear by
+                * writing 1, and writing 0 has no effect. So, the only relevant
                 * information is the single bit we're interested in, all others should
                 * be written as 0 so they will be left unchanged.
                 */
@@ -377,8 +370,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
                                                   bit_reg_info->
                                                   access_bit_mask);
                if (value) {
-                       status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
-                                                       ACPI_REGISTER_PM1_STATUS,
+                       status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
                                                        (u16) value);
                        register_value = 0;
                }
@@ -391,8 +383,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
                                           bit_reg_info->access_bit_mask,
                                           value);
 
-               status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
-                                               ACPI_REGISTER_PM1_ENABLE,
+               status = acpi_hw_register_write(ACPI_REGISTER_PM1_ENABLE,
                                                (u16) register_value);
                break;
 
@@ -411,15 +402,13 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
                                           bit_reg_info->access_bit_mask,
                                           value);
 
-               status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
-                                               ACPI_REGISTER_PM1_CONTROL,
+               status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
                                                (u16) register_value);
                break;
 
        case ACPI_REGISTER_PM2_CONTROL:
 
-               status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
-                                              ACPI_REGISTER_PM2_CONTROL,
+               status = acpi_hw_register_read(ACPI_REGISTER_PM2_CONTROL,
                                               &register_value);
                if (ACPI_FAILURE(status)) {
                        goto unlock_and_exit;
@@ -428,8 +417,9 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
                ACPI_DEBUG_PRINT((ACPI_DB_IO,
                                  "PM2 control: Read %X from %8.8X%8.8X\n",
                                  register_value,
-                                 ACPI_FORMAT_UINT64(acpi_gbl_FADT->
-                                                    xpm2_cnt_blk.address)));
+                                 ACPI_FORMAT_UINT64(acpi_gbl_FADT.
+                                                    xpm2_control_block.
+                                                    address)));
 
                ACPI_REGISTER_INSERT_VALUE(register_value,
                                           bit_reg_info->bit_position,
@@ -439,11 +429,11 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
                ACPI_DEBUG_PRINT((ACPI_DB_IO,
                                  "About to write %4.4X to %8.8X%8.8X\n",
                                  register_value,
-                                 ACPI_FORMAT_UINT64(acpi_gbl_FADT->
-                                                    xpm2_cnt_blk.address)));
+                                 ACPI_FORMAT_UINT64(acpi_gbl_FADT.
+                                                    xpm2_control_block.
+                                                    address)));
 
-               status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
-                                               ACPI_REGISTER_PM2_CONTROL,
+               status = acpi_hw_register_write(ACPI_REGISTER_PM2_CONTROL,
                                                (u8) (register_value));
                break;
 
@@ -453,9 +443,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
 
       unlock_and_exit:
 
-       if (flags & ACPI_MTX_LOCK) {
-               (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
-       }
+       acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
 
        /* Normalize the value that was read */
 
@@ -469,54 +457,44 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
        return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_set_register);
+ACPI_EXPORT_SYMBOL(acpi_set_register)
 
 /******************************************************************************
  *
  * FUNCTION:    acpi_hw_register_read
  *
- * PARAMETERS:  use_lock            - Mutex hw access
- *              register_id         - register_iD + Offset
+ * PARAMETERS:  register_id         - ACPI Register ID
  *              return_value        - Where the register value is returned
  *
  * RETURN:      Status and the value read.
  *
- * DESCRIPTION: Acpi register read function.  Registers are read at the
- *              given offset.
+ * DESCRIPTION: Read from the specified ACPI register
  *
  ******************************************************************************/
-
 acpi_status
-acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
+acpi_hw_register_read(u32 register_id, u32 * return_value)
 {
        u32 value1 = 0;
        u32 value2 = 0;
        acpi_status status;
 
-       ACPI_FUNCTION_TRACE("hw_register_read");
-
-       if (ACPI_MTX_LOCK == use_lock) {
-               status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
-               if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
-               }
-       }
+       ACPI_FUNCTION_TRACE(hw_register_read);
 
        switch (register_id) {
        case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
 
                status =
                    acpi_hw_low_level_read(16, &value1,
-                                          &acpi_gbl_FADT->xpm1a_evt_blk);
+                                          &acpi_gbl_FADT.xpm1a_event_block);
                if (ACPI_FAILURE(status)) {
-                       goto unlock_and_exit;
+                       goto exit;
                }
 
                /* PM1B is optional */
 
                status =
                    acpi_hw_low_level_read(16, &value2,
-                                          &acpi_gbl_FADT->xpm1b_evt_blk);
+                                          &acpi_gbl_FADT.xpm1b_event_block);
                value1 |= value2;
                break;
 
@@ -525,7 +503,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
                status =
                    acpi_hw_low_level_read(16, &value1, &acpi_gbl_xpm1a_enable);
                if (ACPI_FAILURE(status)) {
-                       goto unlock_and_exit;
+                       goto exit;
                }
 
                /* PM1B is optional */
@@ -539,14 +517,14 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
 
                status =
                    acpi_hw_low_level_read(16, &value1,
-                                          &acpi_gbl_FADT->xpm1a_cnt_blk);
+                                          &acpi_gbl_FADT.xpm1a_control_block);
                if (ACPI_FAILURE(status)) {
-                       goto unlock_and_exit;
+                       goto exit;
                }
 
                status =
                    acpi_hw_low_level_read(16, &value2,
-                                          &acpi_gbl_FADT->xpm1b_cnt_blk);
+                                          &acpi_gbl_FADT.xpm1b_control_block);
                value1 |= value2;
                break;
 
@@ -554,32 +532,29 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
 
                status =
                    acpi_hw_low_level_read(8, &value1,
-                                          &acpi_gbl_FADT->xpm2_cnt_blk);
+                                          &acpi_gbl_FADT.xpm2_control_block);
                break;
 
        case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
 
                status =
                    acpi_hw_low_level_read(32, &value1,
-                                          &acpi_gbl_FADT->xpm_tmr_blk);
+                                          &acpi_gbl_FADT.xpm_timer_block);
                break;
 
        case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
 
-               status = acpi_os_read_port(acpi_gbl_FADT->smi_cmd, &value1, 8);
+               status =
+                   acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8);
                break;
 
        default:
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown Register ID: %X\n",
-                                 register_id));
+               ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id));
                status = AE_BAD_PARAMETER;
                break;
        }
 
-      unlock_and_exit:
-       if (ACPI_MTX_LOCK == use_lock) {
-               (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
-       }
+      exit:
 
        if (ACPI_SUCCESS(status)) {
                *return_value = value1;
@@ -592,45 +567,65 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
  *
  * FUNCTION:    acpi_hw_register_write
  *
- * PARAMETERS:  use_lock            - Mutex hw access
- *              register_id         - register_iD + Offset
+ * PARAMETERS:  register_id         - ACPI Register ID
  *              Value               - The value to write
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Acpi register Write function.  Registers are written at the
- *              given offset.
+ * DESCRIPTION: Write to the specified ACPI register
+ *
+ * NOTE: In accordance with the ACPI specification, this function automatically
+ * preserves the value of the following bits, meaning that these bits cannot be
+ * changed via this interface:
+ *
+ * PM1_CONTROL[0] = SCI_EN
+ * PM1_CONTROL[9]
+ * PM1_STATUS[11]
+ *
+ * ACPI References:
+ * 1) Hardware Ignored Bits: When software writes to a register with ignored
+ *      bit fields, it preserves the ignored bit fields
+ * 2) SCI_EN: OSPM always preserves this bit position
  *
  ******************************************************************************/
 
-acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
+acpi_status acpi_hw_register_write(u32 register_id, u32 value)
 {
        acpi_status status;
+       u32 read_value;
 
-       ACPI_FUNCTION_TRACE("hw_register_write");
+       ACPI_FUNCTION_TRACE(hw_register_write);
 
-       if (ACPI_MTX_LOCK == use_lock) {
-               status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+       switch (register_id) {
+       case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
+
+               /* Perform a read first to preserve certain bits (per ACPI spec) */
+
+               status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS,
+                                              &read_value);
                if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
+                       goto exit;
                }
-       }
 
-       switch (register_id) {
-       case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
+               /* Insert the bits to be preserved */
+
+               ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS,
+                                read_value);
+
+               /* Now we can write the data */
 
                status =
                    acpi_hw_low_level_write(16, value,
-                                           &acpi_gbl_FADT->xpm1a_evt_blk);
+                                           &acpi_gbl_FADT.xpm1a_event_block);
                if (ACPI_FAILURE(status)) {
-                       goto unlock_and_exit;
+                       goto exit;
                }
 
                /* PM1B is optional */
 
                status =
                    acpi_hw_low_level_write(16, value,
-                                           &acpi_gbl_FADT->xpm1b_evt_blk);
+                                           &acpi_gbl_FADT.xpm1b_event_block);
                break;
 
        case ACPI_REGISTER_PM1_ENABLE:  /* 16-bit access */
@@ -638,7 +633,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
                status =
                    acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1a_enable);
                if (ACPI_FAILURE(status)) {
-                       goto unlock_and_exit;
+                       goto exit;
                }
 
                /* PM1B is optional */
@@ -649,51 +644,68 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
 
        case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
 
+               /*
+                * Perform a read first to preserve certain bits (per ACPI spec)
+                */
+               status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
+                                              &read_value);
+               if (ACPI_FAILURE(status)) {
+                       goto exit;
+               }
+
+               /* Insert the bits to be preserved */
+
+               ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
+                                read_value);
+
+               /* Now we can write the data */
+
                status =
                    acpi_hw_low_level_write(16, value,
-                                           &acpi_gbl_FADT->xpm1a_cnt_blk);
+                                           &acpi_gbl_FADT.xpm1a_control_block);
                if (ACPI_FAILURE(status)) {
-                       goto unlock_and_exit;
+                       goto exit;
                }
 
                status =
                    acpi_hw_low_level_write(16, value,
-                                           &acpi_gbl_FADT->xpm1b_cnt_blk);
+                                           &acpi_gbl_FADT.xpm1b_control_block);
                break;
 
        case ACPI_REGISTER_PM1A_CONTROL:        /* 16-bit access */
 
                status =
                    acpi_hw_low_level_write(16, value,
-                                           &acpi_gbl_FADT->xpm1a_cnt_blk);
+                                           &acpi_gbl_FADT.xpm1a_control_block);
                break;
 
        case ACPI_REGISTER_PM1B_CONTROL:        /* 16-bit access */
 
                status =
                    acpi_hw_low_level_write(16, value,
-                                           &acpi_gbl_FADT->xpm1b_cnt_blk);
+                                           &acpi_gbl_FADT.xpm1b_control_block);
                break;
 
        case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
 
                status =
                    acpi_hw_low_level_write(8, value,
-                                           &acpi_gbl_FADT->xpm2_cnt_blk);
+                                           &acpi_gbl_FADT.xpm2_control_block);
                break;
 
        case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
 
                status =
                    acpi_hw_low_level_write(32, value,
-                                           &acpi_gbl_FADT->xpm_tmr_blk);
+                                           &acpi_gbl_FADT.xpm_timer_block);
                break;
 
        case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
 
                /* SMI_CMD is currently always in IO space */
 
-               status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, value, 8);
+               status =
+                   acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8);
                break;
 
        default:
@@ -701,11 +713,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
                break;
        }
 
-      unlock_and_exit:
-       if (ACPI_MTX_LOCK == use_lock) {
-               (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
-       }
-
+      exit:
        return_ACPI_STATUS(status);
 }
 
@@ -729,7 +737,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
        u64 address;
        acpi_status status;
 
-       ACPI_FUNCTION_NAME("hw_low_level_read");
+       ACPI_FUNCTION_NAME(hw_low_level_read);
 
        /*
         * Must have a valid pointer to a GAS structure, and
@@ -740,7 +748,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
                return (AE_OK);
        }
 
-       /* Get a local copy of the address.  Handles possible alignment issues */
+       /* Get a local copy of the address. Handles possible alignment issues */
 
        ACPI_MOVE_64_TO_64(&address, &reg->address);
        if (!address) {
@@ -752,7 +760,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
         * Two address spaces supported: Memory or IO.
         * PCI_Config is not supported here because the GAS struct is insufficient
         */
-       switch (reg->address_space_id) {
+       switch (reg->space_id) {
        case ACPI_ADR_SPACE_SYSTEM_MEMORY:
 
                status = acpi_os_read_memory((acpi_physical_address) address,
@@ -761,22 +769,20 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
 
        case ACPI_ADR_SPACE_SYSTEM_IO:
 
-               status = acpi_os_read_port((acpi_io_address) address,
-                                          value, width);
+               status =
+                   acpi_os_read_port((acpi_io_address) address, value, width);
                break;
 
        default:
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Unsupported address space: %X\n",
-                                 reg->address_space_id));
+               ACPI_ERROR((AE_INFO,
+                           "Unsupported address space: %X", reg->space_id));
                return (AE_BAD_PARAMETER);
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_IO,
                          "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
-                         *value, width,
-                         ACPI_FORMAT_UINT64(address),
-                         acpi_ut_get_region_name(reg->address_space_id)));
+                         *value, width, ACPI_FORMAT_UINT64(address),
+                         acpi_ut_get_region_name(reg->space_id)));
 
        return (status);
 }
@@ -801,7 +807,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
        u64 address;
        acpi_status status;
 
-       ACPI_FUNCTION_NAME("hw_low_level_write");
+       ACPI_FUNCTION_NAME(hw_low_level_write);
 
        /*
         * Must have a valid pointer to a GAS structure, and
@@ -812,7 +818,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
                return (AE_OK);
        }
 
-       /* Get a local copy of the address.  Handles possible alignment issues */
+       /* Get a local copy of the address. Handles possible alignment issues */
 
        ACPI_MOVE_64_TO_64(&address, &reg->address);
        if (!address) {
@@ -823,7 +829,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
         * Two address spaces supported: Memory or IO.
         * PCI_Config is not supported here because the GAS struct is insufficient
         */
-       switch (reg->address_space_id) {
+       switch (reg->space_id) {
        case ACPI_ADR_SPACE_SYSTEM_MEMORY:
 
                status = acpi_os_write_memory((acpi_physical_address) address,
@@ -832,22 +838,20 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
 
        case ACPI_ADR_SPACE_SYSTEM_IO:
 
-               status = acpi_os_write_port((acpi_io_address) address,
-                                           value, width);
+               status = acpi_os_write_port((acpi_io_address) address, value,
+                                           width);
                break;
 
        default:
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Unsupported address space: %X\n",
-                                 reg->address_space_id));
+               ACPI_ERROR((AE_INFO,
+                           "Unsupported address space: %X", reg->space_id));
                return (AE_BAD_PARAMETER);
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_IO,
                          "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
-                         value, width,
-                         ACPI_FORMAT_UINT64(address),
-                         acpi_ut_get_region_name(reg->address_space_id)));
+                         value, width, ACPI_FORMAT_UINT64(address),
+                         acpi_ut_get_region_name(reg->space_id)));
 
        return (status);
 }