diff --git a/[refs] b/[refs] index b399e21bf36e..97c2d52e6867 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: bb45e394e21eb2abc710ad43d98ebac1069bf355 +refs/heads/master: 5190726765b40774c069e187a958e10ccd970e65 diff --git a/trunk/drivers/acpi/button.c b/trunk/drivers/acpi/button.c index 76bbb78a5ad9..e643a0936dc4 100644 --- a/trunk/drivers/acpi/button.c +++ b/trunk/drivers/acpi/button.c @@ -430,7 +430,6 @@ static int acpi_button_add(struct acpi_device *device) /* Button's GPE is run-wake GPE */ acpi_enable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number); - device->wakeup.run_wake_count++; device_set_wakeup_enable(&device->dev, true); } @@ -453,7 +452,6 @@ static int acpi_button_remove(struct acpi_device *device, int type) if (device->wakeup.flags.valid) { acpi_disable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number); - device->wakeup.run_wake_count--; device_set_wakeup_enable(&device->dev, false); } diff --git a/trunk/drivers/acpi/nvs.c b/trunk/drivers/acpi/nvs.c index 096787b43c96..fa5a1df42b79 100644 --- a/trunk/drivers/acpi/nvs.c +++ b/trunk/drivers/acpi/nvs.c @@ -26,7 +26,6 @@ struct nvs_page { unsigned int size; void *kaddr; void *data; - bool unmap; struct list_head node; }; @@ -45,9 +44,6 @@ 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; @@ -85,13 +81,7 @@ void suspend_nvs_free(void) free_page((unsigned long)entry->data); entry->data = NULL; if (entry->kaddr) { - if (entry->unmap) { - iounmap(entry->kaddr); - entry->unmap = false; - } else { - acpi_os_unmap_memory(entry->kaddr, - entry->size); - } + iounmap(entry->kaddr); entry->kaddr = NULL; } } @@ -125,14 +115,8 @@ int suspend_nvs_save(void) list_for_each_entry(entry, &nvs_list, node) if (entry->data) { - 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; - } + entry->kaddr = acpi_os_ioremap(entry->phys_start, + entry->size); if (!entry->kaddr) { suspend_nvs_free(); return -ENOMEM; diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index 52ca8721bc9c..c90c76aa7f8b 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -105,11 +105,11 @@ struct acpi_ioremap { void __iomem *virt; acpi_physical_address phys; acpi_size size; - unsigned long refcount; + struct kref ref; }; static LIST_HEAD(acpi_ioremaps); -static DEFINE_MUTEX(acpi_ioremap_lock); +static DEFINE_SPINLOCK(acpi_ioremap_lock); static void __init acpi_osi_setup_late(void); @@ -285,22 +285,6 @@ acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size) return NULL; } -void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size) -{ - struct acpi_ioremap *map; - void __iomem *virt = NULL; - - mutex_lock(&acpi_ioremap_lock); - map = acpi_map_lookup(phys, size); - if (map) { - virt = map->virt + (phys - map->phys); - map->refcount++; - } - mutex_unlock(&acpi_ioremap_lock); - return virt; -} -EXPORT_SYMBOL_GPL(acpi_os_get_iomem); - /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ static struct acpi_ioremap * acpi_map_lookup_virt(void __iomem *virt, acpi_size size) @@ -318,7 +302,8 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) void __iomem *__init_refok acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { - struct acpi_ioremap *map; + struct acpi_ioremap *map, *tmp_map; + unsigned long flags; void __iomem *virt; acpi_physical_address pg_off; acpi_size pg_sz; @@ -331,25 +316,14 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) if (!acpi_gbl_permanent_mmap) return __acpi_map_table((unsigned long)phys, size); - mutex_lock(&acpi_ioremap_lock); - /* Check if there's a suitable mapping already. */ - map = acpi_map_lookup(phys, size); - if (map) { - map->refcount++; - goto out; - } - map = kzalloc(sizeof(*map), GFP_KERNEL); - if (!map) { - mutex_unlock(&acpi_ioremap_lock); + if (!map) return NULL; - } pg_off = round_down(phys, PAGE_SIZE); pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; virt = acpi_os_ioremap(pg_off, pg_sz); if (!virt) { - mutex_unlock(&acpi_ioremap_lock); kfree(map); return NULL; } @@ -358,51 +332,62 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) map->virt = virt; map->phys = pg_off; map->size = pg_sz; - map->refcount = 1; - + kref_init(&map->ref); + + spin_lock_irqsave(&acpi_ioremap_lock, flags); + /* Check if page has already been mapped. */ + tmp_map = acpi_map_lookup(phys, size); + if (tmp_map) { + kref_get(&tmp_map->ref); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + iounmap(map->virt); + kfree(map); + return tmp_map->virt + (phys - tmp_map->phys); + } list_add_tail_rcu(&map->list, &acpi_ioremaps); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); - out: - mutex_unlock(&acpi_ioremap_lock); return map->virt + (phys - map->phys); } EXPORT_SYMBOL_GPL(acpi_os_map_memory); -static void acpi_os_drop_map_ref(struct acpi_ioremap *map) +static void acpi_kref_del_iomap(struct kref *ref) { - if (!--map->refcount) - list_del_rcu(&map->list); -} + struct acpi_ioremap *map; -static void acpi_os_map_cleanup(struct acpi_ioremap *map) -{ - if (!map->refcount) { - synchronize_rcu(); - iounmap(map->virt); - kfree(map); - } + map = container_of(ref, struct acpi_ioremap, ref); + list_del_rcu(&map->list); } void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) { struct acpi_ioremap *map; + unsigned long flags; + int del; if (!acpi_gbl_permanent_mmap) { __acpi_unmap_table(virt, size); return; } - mutex_lock(&acpi_ioremap_lock); + spin_lock_irqsave(&acpi_ioremap_lock, flags); map = acpi_map_lookup_virt(virt, size); if (!map) { - mutex_unlock(&acpi_ioremap_lock); - WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt); + dump_stack(); return; } - acpi_os_drop_map_ref(map); - mutex_unlock(&acpi_ioremap_lock); - acpi_os_map_cleanup(map); + del = kref_put(&map->ref, acpi_kref_del_iomap); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); + + if (!del) + return; + + synchronize_rcu(); + iounmap(map->virt); + kfree(map); } EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); @@ -412,7 +397,7 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size) __acpi_unmap_table(virt, size); } -static int acpi_os_map_generic_address(struct acpi_generic_address *addr) +int acpi_os_map_generic_address(struct acpi_generic_address *addr) { void __iomem *virt; @@ -428,10 +413,13 @@ static int acpi_os_map_generic_address(struct acpi_generic_address *addr) return 0; } +EXPORT_SYMBOL_GPL(acpi_os_map_generic_address); -static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) +void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) { - struct acpi_ioremap *map; + void __iomem *virt; + unsigned long flags; + acpi_size size = addr->bit_width / 8; if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) return; @@ -439,17 +427,13 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) if (!addr->address || !addr->bit_width) return; - mutex_lock(&acpi_ioremap_lock); - map = acpi_map_lookup(addr->address, addr->bit_width / 8); - if (!map) { - mutex_unlock(&acpi_ioremap_lock); - return; - } - acpi_os_drop_map_ref(map); - mutex_unlock(&acpi_ioremap_lock); + spin_lock_irqsave(&acpi_ioremap_lock, flags); + virt = acpi_map_vaddr_lookup(addr->address, size); + spin_unlock_irqrestore(&acpi_ioremap_lock, flags); - acpi_os_map_cleanup(map); + acpi_os_unmap_memory(virt, size); } +EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address); #ifdef ACPI_FUTURE_USAGE acpi_status diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index b99e62494607..b136c9c1e531 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -797,7 +797,6 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) acpi_status status; acpi_event_status event_status; - device->wakeup.run_wake_count = 0; device->wakeup.flags.notifier_present = 0; /* Power button, Lid switch always enable wakeup */ diff --git a/trunk/drivers/pci/pci-acpi.c b/trunk/drivers/pci/pci-acpi.c index 6fe0772e0e7d..7c3b18e78cee 100644 --- a/trunk/drivers/pci/pci-acpi.c +++ b/trunk/drivers/pci/pci-acpi.c @@ -293,19 +293,11 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable) } if (enable) { - if (!dev->wakeup.run_wake_count++) { - acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); - acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); - } - } else if (dev->wakeup.run_wake_count > 0) { - if (!--dev->wakeup.run_wake_count) { - acpi_disable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); - acpi_disable_wakeup_device_power(dev); - } + acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); + acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); } else { - error = -EALREADY; + acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); + acpi_disable_wakeup_device_power(dev); } return error; diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index 78ca429929f7..f50ebb9bc53b 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -250,7 +250,6 @@ struct acpi_device_wakeup { struct acpi_handle_list resources; struct acpi_device_wakeup_flags flags; int prepare_count; - int run_wake_count; }; /* Device */ diff --git a/trunk/include/linux/acpi_io.h b/trunk/include/linux/acpi_io.h index 4afd7102459d..7180013a4a3a 100644 --- a/trunk/include/linux/acpi_io.h +++ b/trunk/include/linux/acpi_io.h @@ -10,6 +10,7 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, return ioremap_cache(phys, size); } -void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size); +int acpi_os_map_generic_address(struct acpi_generic_address *addr); +void acpi_os_unmap_generic_address(struct acpi_generic_address *addr); #endif