summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-02-08 23:38:38 +0100
committerRafael J. Wysocki <rjw@sisk.pl>2011-02-24 19:58:42 +0100
commitbb45e394e21eb2abc710ad43d98ebac1069bf355 (patch)
tree13e250fb395b358bb8c9471880d3d8fc121d6c2b
parent13606a2de1996f8d83a9ce296f74022bdbadf712 (diff)
downloadblackbird-op-linux-bb45e394e21eb2abc710ad43d98ebac1069bf355.tar.gz
blackbird-op-linux-bb45e394e21eb2abc710ad43d98ebac1069bf355.zip
ACPI / PM: Use existing ACPI iomaps for NVS save/restore (v2)
Modify the NVS save/restore code to use acpi_os_get_iomem() and acpi_os_unmap_memory() to acquire and release references to ACPI iomaps, respectively. If there's no ACPI iomap corresponding to the given NVS page, acpi_os_ioremap() is used to map that page and iounmap() is used to unmap it during resume. [If the page is not present in the ACPI iomaps already, it doesn't make sense to add its mapping to the list of ACPI iomaps, because it's going to be thrown away during the subsequent resume anyway.] Testing on my HP nx6325 shows that approx. 90% of the NVS pages have already been mapped by ACPI before suspend and are present in the ACPI iomaps, so this change appears to be the right thing to do in general. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-rw-r--r--drivers/acpi/nvs.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c
index fa5a1df42b79..096787b43c96 100644
--- a/drivers/acpi/nvs.c
+++ b/drivers/acpi/nvs.c
@@ -26,6 +26,7 @@ struct nvs_page {
unsigned int size;
void *kaddr;
void *data;
+ bool unmap;
struct list_head node;
};
@@ -44,6 +45,9 @@ int suspend_nvs_register(unsigned long start, unsigned long size)
{
struct nvs_page *entry, *next;
+ pr_info("PM: Registering ACPI NVS region at %lx (%ld bytes)\n",
+ start, size);
+
while (size > 0) {
unsigned int nr_bytes;
@@ -81,7 +85,13 @@ void suspend_nvs_free(void)
free_page((unsigned long)entry->data);
entry->data = NULL;
if (entry->kaddr) {
- iounmap(entry->kaddr);
+ if (entry->unmap) {
+ iounmap(entry->kaddr);
+ entry->unmap = false;
+ } else {
+ acpi_os_unmap_memory(entry->kaddr,
+ entry->size);
+ }
entry->kaddr = NULL;
}
}
@@ -115,8 +125,14 @@ int suspend_nvs_save(void)
list_for_each_entry(entry, &nvs_list, node)
if (entry->data) {
- entry->kaddr = acpi_os_ioremap(entry->phys_start,
- entry->size);
+ unsigned long phys = entry->phys_start;
+ unsigned int size = entry->size;
+
+ entry->kaddr = acpi_os_get_iomem(phys, size);
+ if (!entry->kaddr) {
+ entry->kaddr = acpi_os_ioremap(phys, size);
+ entry->unmap = !!entry->kaddr;
+ }
if (!entry->kaddr) {
suspend_nvs_free();
return -ENOMEM;
OpenPOWER on IntegriCloud