===================================================================
@@ -81,8 +81,8 @@ struct acpi_ioremap {
};
static LIST_HEAD(acpi_ioremaps);
+static DEFINE_RWLOCK(acpi_ioremaps_list_lock);
static DEFINE_MUTEX(acpi_ioremap_lock);
-#define acpi_ioremap_lock_held() lock_is_held(&acpi_ioremap_lock.dep_map)
static void __init acpi_request_region (struct acpi_generic_address *gas,
unsigned int length, char *desc)
@@ -214,13 +214,13 @@ acpi_physical_address __init acpi_os_get
return pa;
}
-/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
+/* Must be called with 'acpi_ioremap_lock' or 'acpi_ioremaps_list_lock' held. */
static struct acpi_ioremap *
acpi_map_lookup(acpi_physical_address phys, acpi_size size)
{
struct acpi_ioremap *map;
- list_for_each_entry_rcu(map, &acpi_ioremaps, list, acpi_ioremap_lock_held())
+ list_for_each_entry(map, &acpi_ioremaps, list)
if (map->phys <= phys &&
phys + size <= map->phys + map->size)
return map;
@@ -228,7 +228,7 @@ acpi_map_lookup(acpi_physical_address ph
return NULL;
}
-/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
+/* Must be called with 'acpi_ioremap_lock' or 'acpi_ioremaps_list_lock' held. */
static void __iomem *
acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size)
{
@@ -257,13 +257,13 @@ void __iomem *acpi_os_get_iomem(acpi_phy
}
EXPORT_SYMBOL_GPL(acpi_os_get_iomem);
-/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
+/* Must be called with 'acpi_ioremap_lock' or 'acpi_ioremaps_list_lock' held. */
static struct acpi_ioremap *
acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
{
struct acpi_ioremap *map;
- list_for_each_entry_rcu(map, &acpi_ioremaps, list, acpi_ioremap_lock_held())
+ list_for_each_entry(map, &acpi_ioremaps, list)
if (map->virt <= virt &&
virt + size <= map->virt + map->size)
return map;
@@ -360,7 +360,11 @@ void __iomem __ref
map->size = pg_sz;
map->refcount = 1;
- list_add_tail_rcu(&map->list, &acpi_ioremaps);
+ write_lock_irq(&acpi_ioremaps_list_lock);
+
+ list_add_tail(&map->list, &acpi_ioremaps);
+
+ write_unlock_irq(&acpi_ioremaps_list_lock);
out:
mutex_unlock(&acpi_ioremap_lock);
@@ -379,14 +383,18 @@ static unsigned long acpi_os_drop_map_re
{
unsigned long refcount = --map->refcount;
- if (!refcount)
- list_del_rcu(&map->list);
+ if (!refcount) {
+ write_lock_irq(&acpi_ioremaps_list_lock);
+
+ list_del(&map->list);
+
+ write_unlock_irq(&acpi_ioremaps_list_lock);
+ }
return refcount;
}
static void acpi_os_map_cleanup(struct acpi_ioremap *map)
{
- synchronize_rcu_expedited();
acpi_unmap(map->phys, map->virt);
kfree(map);
}
@@ -704,18 +712,23 @@ acpi_status
acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
{
void __iomem *virt_addr;
+ unsigned long flags;
unsigned int size = width / 8;
bool unmap = false;
u64 dummy;
int error;
- rcu_read_lock();
+ read_lock_irqsave(&acpi_ioremaps_list_lock, flags);
+
virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
if (!virt_addr) {
- rcu_read_unlock();
+
+ read_unlock_irqrestore(&acpi_ioremaps_list_lock, flags);
+
virt_addr = acpi_os_ioremap(phys_addr, size);
if (!virt_addr)
return AE_BAD_ADDRESS;
+
unmap = true;
}
@@ -728,7 +741,7 @@ acpi_os_read_memory(acpi_physical_addres
if (unmap)
iounmap(virt_addr);
else
- rcu_read_unlock();
+ read_unlock_irqrestore(&acpi_ioremaps_list_lock, flags);
return AE_OK;
}
@@ -737,16 +750,21 @@ acpi_status
acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
{
void __iomem *virt_addr;
+ unsigned long flags;
unsigned int size = width / 8;
bool unmap = false;
- rcu_read_lock();
+ read_lock_irqsave(&acpi_ioremaps_list_lock, flags);
+
virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
if (!virt_addr) {
- rcu_read_unlock();
+
+ read_unlock_irqrestore(&acpi_ioremaps_list_lock, flags);
+
virt_addr = acpi_os_ioremap(phys_addr, size);
if (!virt_addr)
return AE_BAD_ADDRESS;
+
unmap = true;
}
@@ -770,7 +788,7 @@ acpi_os_write_memory(acpi_physical_addre
if (unmap)
iounmap(virt_addr);
else
- rcu_read_unlock();
+ read_unlock_irqrestore(&acpi_ioremaps_list_lock, flags);
return AE_OK;
}