acpi_os_unmap_memory(table, length);
        return_ACPI_STATUS(AE_OK);
 }
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_get_table
+ *
+ * PARAMETERS:  table_desc          - Table descriptor
+ *              out_table           - Where the pointer to the table is returned
+ *
+ * RETURN:      Status and pointer to the requested table
+ *
+ * DESCRIPTION: Increase a reference to a table descriptor and return the
+ *              validated table pointer.
+ *              If the table descriptor is an entry of the root table list,
+ *              this API must be invoked with ACPI_MTX_TABLES acquired.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_tb_get_table(struct acpi_table_desc *table_desc,
+                 struct acpi_table_header **out_table)
+{
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(acpi_tb_get_table);
+
+       if (table_desc->validation_count == 0) {
+
+               /* Table need to be "VALIDATED" */
+
+               status = acpi_tb_validate_table(table_desc);
+               if (ACPI_FAILURE(status)) {
+                       return_ACPI_STATUS(status);
+               }
+       }
+
+       table_desc->validation_count++;
+       if (table_desc->validation_count == 0) {
+               ACPI_ERROR((AE_INFO,
+                           "Table %p, Validation count is zero after increment\n",
+                           table_desc));
+               table_desc->validation_count--;
+               return_ACPI_STATUS(AE_LIMIT);
+       }
+
+       *out_table = table_desc->pointer;
+       return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_put_table
+ *
+ * PARAMETERS:  table_desc          - Table descriptor
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Decrease a reference to a table descriptor and release the
+ *              validated table pointer if no references.
+ *              If the table descriptor is an entry of the root table list,
+ *              this API must be invoked with ACPI_MTX_TABLES acquired.
+ *
+ ******************************************************************************/
+
+void acpi_tb_put_table(struct acpi_table_desc *table_desc)
+{
+
+       ACPI_FUNCTION_TRACE(acpi_tb_put_table);
+
+       if (table_desc->validation_count == 0) {
+               ACPI_WARNING((AE_INFO,
+                             "Table %p, Validation count is zero before decrement\n",
+                             table_desc));
+               return_VOID;
+       }
+       table_desc->validation_count--;
+
+       if (table_desc->validation_count == 0) {
+
+               /* Table need to be "INVALIDATED" */
+
+               acpi_tb_invalidate_table(table_desc);
+       }
+
+       return_VOID;
+}
 
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_get_table_with_size
+ * FUNCTION:    acpi_get_table
  *
  * PARAMETERS:  signature           - ACPI signature of needed table
  *              instance            - Which instance (for SSDTs)
  *
  * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
  *              RSDT/XSDT.
+ *              Note that an early stage acpi_get_table() call must be paired
+ *              with an early stage acpi_put_table() call. otherwise the table
+ *              pointer mapped by the early stage mapping implementation may be
+ *              erroneously unmapped by the late stage unmapping implementation
+ *              in an acpi_put_table() invoked during the late stage.
  *
  ******************************************************************************/
 acpi_status
-acpi_get_table_with_size(char *signature,
-              u32 instance, struct acpi_table_header **out_table,
-              acpi_size *tbl_size)
+acpi_get_table(char *signature,
+              u32 instance, struct acpi_table_header ** out_table)
 {
        u32 i;
        u32 j;
-       acpi_status status;
+       acpi_status status = AE_NOT_FOUND;
+       struct acpi_table_desc *table_desc;
 
        /* Parameter validation */
 
                return (AE_BAD_PARAMETER);
        }
 
+       /*
+        * Note that the following line is required by some OSPMs, they only
+        * check if the returned table is NULL instead of the returned status
+        * to determined if this function is succeeded.
+        */
+       *out_table = NULL;
+
+       (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
        /* Walk the root table list */
 
        for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
             i++) {
-               if (!ACPI_COMPARE_NAME
-                   (&(acpi_gbl_root_table_list.tables[i].signature),
-                    signature)) {
+               table_desc = &acpi_gbl_root_table_list.tables[i];
+
+               if (!ACPI_COMPARE_NAME(&table_desc->signature, signature)) {
                        continue;
                }
 
                        continue;
                }
 
-               status =
-                   acpi_tb_validate_table(&acpi_gbl_root_table_list.tables[i]);
-               if (ACPI_SUCCESS(status)) {
-                       *out_table = acpi_gbl_root_table_list.tables[i].pointer;
-                       *tbl_size = acpi_gbl_root_table_list.tables[i].length;
-               }
-
-               if (!acpi_gbl_permanent_mmap) {
-                       acpi_gbl_root_table_list.tables[i].pointer = NULL;
-               }
-
-               return (status);
+               status = acpi_tb_get_table(table_desc, out_table);
+               break;
        }
 
-       return (AE_NOT_FOUND);
+       (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+       return (status);
 }
 
-ACPI_EXPORT_SYMBOL(acpi_get_table_with_size)
+ACPI_EXPORT_SYMBOL(acpi_get_table)
 
-acpi_status
-acpi_get_table(char *signature,
-              u32 instance, struct acpi_table_header **out_table)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_put_table
+ *
+ * PARAMETERS:  table               - The pointer to the table
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Release a table returned by acpi_get_table() and its clones.
+ *              Note that it is not safe if this function was invoked after an
+ *              uninstallation happened to the original table descriptor.
+ *              Currently there is no OSPMs' requirement to handle such
+ *              situations.
+ *
+ ******************************************************************************/
+void acpi_put_table(struct acpi_table_header *table)
 {
-       acpi_size tbl_size;
+       u32 i;
+       struct acpi_table_desc *table_desc;
+
+       ACPI_FUNCTION_TRACE(acpi_put_table);
+
+       (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
+       /* Walk the root table list */
+
+       for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
+               table_desc = &acpi_gbl_root_table_list.tables[i];
 
-       return acpi_get_table_with_size(signature,
-                      instance, out_table, &tbl_size);
+               if (table_desc->pointer != table) {
+                       continue;
+               }
+
+               acpi_tb_put_table(table_desc);
+               break;
+       }
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+       return_VOID;
 }
 
-ACPI_EXPORT_SYMBOL(acpi_get_table)
+ACPI_EXPORT_SYMBOL(acpi_put_table)
 
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_table_by_index
  *
  * PARAMETERS:  table_index         - Table index
- *              table               - Where the pointer to the table is returned
+ *              out_table           - Where the pointer to the table is returned
  *
  * RETURN:      Status and pointer to the requested table
  *
  *
  ******************************************************************************/
 acpi_status
-acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
+acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table)
 {
        acpi_status status;
 
 
        /* Parameter validation */
 
-       if (!table) {
+       if (!out_table) {
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
+       /*
+        * Note that the following line is required by some OSPMs, they only
+        * check if the returned table is NULL instead of the returned status
+        * to determined if this function is succeeded.
+        */
+       *out_table = NULL;
+
        (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 
        /* Validate index */
 
        if (table_index >= acpi_gbl_root_table_list.current_table_count) {
-               (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
-               return_ACPI_STATUS(AE_BAD_PARAMETER);
+               status = AE_BAD_PARAMETER;
+               goto unlock_and_exit;
        }
 
-       if (!acpi_gbl_root_table_list.tables[table_index].pointer) {
-
-               /* Table is not mapped, map it */
+       status =
+           acpi_tb_get_table(&acpi_gbl_root_table_list.tables[table_index],
+                             out_table);
 
-               status =
-                   acpi_tb_validate_table(&acpi_gbl_root_table_list.
-                                          tables[table_index]);
-               if (ACPI_FAILURE(status)) {
-                       (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
-                       return_ACPI_STATUS(status);
-               }
-       }
-
-       *table = acpi_gbl_root_table_list.tables[table_index].pointer;
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
-       return_ACPI_STATUS(AE_OK);
+       return_ACPI_STATUS(status);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
 
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
 
+/*******************************************************************************
+ *
+ * acpi_get_table_with_size()/early_acpi_os_unmap_memory():
+ *
+ * These 2 functions are traditionally used by Linux to map/unmap physical
+ * addressed ACPI tables during the early stage.
+ * They are deprectated now. Do not use them in the new code, but use
+ * acpi_get_table()/acpi_put_table() instead.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_get_table_with_size(char *signature,
+              u32 instance, struct acpi_table_header **out_table,
+              acpi_size *tbl_size)
+{
+       acpi_status status;
+
+       status = acpi_get_table(signature, instance, out_table);
+       if (ACPI_SUCCESS(status)) {
+               /*
+                * "tbl_size" is no longer used by
+                * early_acpi_os_unmap_memory(), but is still used by the
+                * ACPI table drivers. So sets it to the length of the
+                * table when the tbl_size is requested.
+                * "out_table" is not sanity checked as AE_BAD_PARAMETER
+                * is returned if it is NULL.
+                */
+               if (tbl_size && *out_table)
+                       *tbl_size = (*out_table)->length;
+       }
+
+       return (status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_table_with_size)
+
 void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 {
-       if (!acpi_gbl_permanent_mmap)
-               __acpi_unmap_table(virt, size);
+       acpi_put_table(ACPI_CAST_PTR(struct acpi_table_header, virt));
 }
 
 int acpi_os_map_generic_address(struct acpi_generic_address *gas)