diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-02-08 17:38:15 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-02-24 13:58:42 -0500 |
commit | b7c1fadd6c2eead56d0664a3a921980120de0c11 (patch) | |
tree | ccd0788ca079460db52be43c6f6e0273e300891a /drivers | |
parent | 7ffd0443f2502478545e23e194b7eb8e16376072 (diff) |
ACPI: Do not use krefs under a mutex in osl.c
The reference counting of ACPI iomaps is carried out entirely under
acpi_ioremap_lock, so it is sufficient to use simple counters instead
of krefs for this purpose.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/osl.c | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 445f205752a2..5389f9f2e2ff 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -105,7 +105,7 @@ struct acpi_ioremap { | |||
105 | void __iomem *virt; | 105 | void __iomem *virt; |
106 | acpi_physical_address phys; | 106 | acpi_physical_address phys; |
107 | acpi_size size; | 107 | acpi_size size; |
108 | struct kref ref; | 108 | unsigned long refcount; |
109 | }; | 109 | }; |
110 | 110 | ||
111 | static LIST_HEAD(acpi_ioremaps); | 111 | static LIST_HEAD(acpi_ioremaps); |
@@ -319,7 +319,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | |||
319 | /* Check if there's a suitable mapping already. */ | 319 | /* Check if there's a suitable mapping already. */ |
320 | map = acpi_map_lookup(phys, size); | 320 | map = acpi_map_lookup(phys, size); |
321 | if (map) { | 321 | if (map) { |
322 | kref_get(&map->ref); | 322 | map->refcount++; |
323 | goto out; | 323 | goto out; |
324 | } | 324 | } |
325 | 325 | ||
@@ -342,7 +342,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | |||
342 | map->virt = virt; | 342 | map->virt = virt; |
343 | map->phys = pg_off; | 343 | map->phys = pg_off; |
344 | map->size = pg_sz; | 344 | map->size = pg_sz; |
345 | kref_init(&map->ref); | 345 | map->refcount = 1; |
346 | 346 | ||
347 | list_add_tail_rcu(&map->list, &acpi_ioremaps); | 347 | list_add_tail_rcu(&map->list, &acpi_ioremaps); |
348 | 348 | ||
@@ -352,25 +352,24 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) | |||
352 | } | 352 | } |
353 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); | 353 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); |
354 | 354 | ||
355 | static void acpi_kref_del_iomap(struct kref *ref) | 355 | static void acpi_os_drop_map_ref(struct acpi_ioremap *map) |
356 | { | 356 | { |
357 | struct acpi_ioremap *map; | 357 | if (!--map->refcount) |
358 | 358 | list_del_rcu(&map->list); | |
359 | map = container_of(ref, struct acpi_ioremap, ref); | ||
360 | list_del_rcu(&map->list); | ||
361 | } | 359 | } |
362 | 360 | ||
363 | static void acpi_os_remove_map(struct acpi_ioremap *map) | 361 | static void acpi_os_map_cleanup(struct acpi_ioremap *map) |
364 | { | 362 | { |
365 | synchronize_rcu(); | 363 | if (!map->refcount) { |
366 | iounmap(map->virt); | 364 | synchronize_rcu(); |
367 | kfree(map); | 365 | iounmap(map->virt); |
366 | kfree(map); | ||
367 | } | ||
368 | } | 368 | } |
369 | 369 | ||
370 | void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | 370 | void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) |
371 | { | 371 | { |
372 | struct acpi_ioremap *map; | 372 | struct acpi_ioremap *map; |
373 | int del; | ||
374 | 373 | ||
375 | if (!acpi_gbl_permanent_mmap) { | 374 | if (!acpi_gbl_permanent_mmap) { |
376 | __acpi_unmap_table(virt, size); | 375 | __acpi_unmap_table(virt, size); |
@@ -384,11 +383,10 @@ void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | |||
384 | WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); | 383 | WARN(true, PREFIX "%s: bad address %p\n", __func__, virt); |
385 | return; | 384 | return; |
386 | } | 385 | } |
387 | del = kref_put(&map->ref, acpi_kref_del_iomap); | 386 | acpi_os_drop_map_ref(map); |
388 | mutex_unlock(&acpi_ioremap_lock); | 387 | mutex_unlock(&acpi_ioremap_lock); |
389 | 388 | ||
390 | if (del) | 389 | acpi_os_map_cleanup(map); |
391 | acpi_os_remove_map(map); | ||
392 | } | 390 | } |
393 | EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); | 391 | EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); |
394 | 392 | ||
@@ -418,7 +416,6 @@ static int acpi_os_map_generic_address(struct acpi_generic_address *addr) | |||
418 | static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) | 416 | static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) |
419 | { | 417 | { |
420 | struct acpi_ioremap *map; | 418 | struct acpi_ioremap *map; |
421 | int del; | ||
422 | 419 | ||
423 | if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) | 420 | if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) |
424 | return; | 421 | return; |
@@ -432,11 +429,10 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) | |||
432 | mutex_unlock(&acpi_ioremap_lock); | 429 | mutex_unlock(&acpi_ioremap_lock); |
433 | return; | 430 | return; |
434 | } | 431 | } |
435 | del = kref_put(&map->ref, acpi_kref_del_iomap); | 432 | acpi_os_drop_map_ref(map); |
436 | mutex_unlock(&acpi_ioremap_lock); | 433 | mutex_unlock(&acpi_ioremap_lock); |
437 | 434 | ||
438 | if (del) | 435 | acpi_os_map_cleanup(map); |
439 | acpi_os_remove_map(map); | ||
440 | } | 436 | } |
441 | 437 | ||
442 | #ifdef ACPI_FUTURE_USAGE | 438 | #ifdef ACPI_FUTURE_USAGE |