@@ -302,21 +302,8 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
iounmap(vaddr);
}
-/**
- * acpi_os_map_iomem - Get a virtual address for a given physical address range.
- * @phys: Start of the physical address range to map.
- * @size: Size of the physical address range to map.
- *
- * Look up the given physical address range in the list of existing ACPI memory
- * mappings. If found, get a reference to it and return a pointer to it (its
- * virtual address). If not found, map it, add it to that list and return a
- * pointer to it.
- *
- * During early init (when acpi_permanent_mmap has not been set yet) this
- * routine simply calls __acpi_map_table() to get the job done.
- */
-void __iomem __ref
-*acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
+static void __iomem __ref *__acpi_os_map_iomem(acpi_physical_address phys,
+ acpi_size size, bool fast_path)
{
struct acpi_ioremap *map;
void __iomem *virt;
@@ -328,8 +315,12 @@ void __iomem __ref
return NULL;
}
- if (!acpi_permanent_mmap)
+ if (!acpi_permanent_mmap) {
+ if (WARN_ON(fast_path))
+ return NULL;
+
return __acpi_map_table((unsigned long)phys, size);
+ }
mutex_lock(&acpi_ioremap_lock);
/* Check if there's a suitable mapping already. */
@@ -339,6 +330,11 @@ void __iomem __ref
goto out;
}
+ if (fast_path) {
+ mutex_unlock(&acpi_ioremap_lock);
+ return NULL;
+ }
+
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (!map) {
mutex_unlock(&acpi_ioremap_lock);
@@ -366,6 +362,25 @@ void __iomem __ref
mutex_unlock(&acpi_ioremap_lock);
return map->virt + (phys - map->phys);
}
+
+/**
+ * acpi_os_map_iomem - Get a virtual address for a given physical address range.
+ * @phys: Start of the physical address range to map.
+ * @size: Size of the physical address range to map.
+ *
+ * Look up the given physical address range in the list of existing ACPI memory
+ * mappings. If found, get a reference to it and return a pointer representing
+ * its virtual address. If not found, map it, add it to that list and return a
+ * pointer representing its virtual address.
+ *
+ * During early init (when acpi_permanent_mmap has not been set yet) call
+ * __acpi_map_table() to obtain the mapping.
+ */
+void __iomem __ref *acpi_os_map_iomem(acpi_physical_address phys,
+ acpi_size size)
+{
+ return __acpi_os_map_iomem(phys, size, false);
+}
EXPORT_SYMBOL_GPL(acpi_os_map_iomem);
void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
@@ -374,6 +389,24 @@ void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
}
EXPORT_SYMBOL_GPL(acpi_os_map_memory);
+/**
+ * acpi_os_map_memory_fast_path - Fast-path physical-to-virtual address mapping.
+ * @phys: Start of the physical address range to map.
+ * @size: Size of the physical address range to map.
+ *
+ * Look up the given physical address range in the list of existing ACPI memory
+ * mappings. If found, get a reference to it and return a pointer representing
+ * its virtual address. If not found, return NULL.
+ *
+ * During early init (when acpi_permanent_mmap has not been set yet) log a
+ * warning and return NULL.
+ */
+void __ref *acpi_os_map_memory_fast_path(acpi_physical_address phys,
+ acpi_size size)
+{
+ return __acpi_os_map_iomem(phys, size, true);
+}
+
/* Must be called with mutex_lock(&acpi_ioremap_lock) */
static unsigned long acpi_os_drop_map_ref(struct acpi_ioremap *map)
{
@@ -1571,6 +1604,8 @@ acpi_status acpi_release_memory(acpi_handle handle, struct resource *res,
return acpi_walk_namespace(ACPI_TYPE_REGION, handle, level,
acpi_deactivate_mem_region, NULL, res, NULL);
+
+ acpi_release_unused_memory_mappings();
}
EXPORT_SYMBOL_GPL(acpi_release_memory);
@@ -139,6 +139,10 @@ static inline void acpi_os_terminate_debugger(void)
* OSL interfaces added by Linux
*/
+void *acpi_os_map_memory_fast_path(acpi_physical_address where, acpi_size length);
+
+#define ACPI_OS_MAP_MEMORY_FAST_PATH(a, s) acpi_os_map_memory_fast_path(a, s)
+
#endif /* __KERNEL__ */
#endif /* __ACLINUXEX_H__ */