ACK: [PATCH 1/1] acpi_init: move to full RCU free for IO mappings
Andy Whitcroft
apw at canonical.com
Fri Sep 23 16:56:31 UTC 2011
On Fri, Sep 23, 2011 at 10:23:03AM -0600, Tim Gardner wrote:
> On 09/23/2011 09:50 AM, Andy Whitcroft wrote:
> >During acpi_init we map and unmap a large number of mappings. The existing
> >code uses 'simple' RCU based free, triggering a full sychronize_rcu()
> >against the caller. If the machine is busy (for example unpacking the
> >initramfs) at the time this triggers a significant delay until all cpus
> >rendevous. Move those to a delayed RCU free callback.
> >
> >For our reference platform this cuts the average acpi_init time in half,
> >dropping boot time by .25s.
> >
> >Signed-off-by: Andy Whitcroft<apw at canonical.com>
> >---
> > drivers/acpi/atomicio.c | 12 +++++++++---
> > drivers/acpi/osl.c | 16 +++++++++++-----
> > 2 files changed, 20 insertions(+), 8 deletions(-)
> >
> >diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c
> >index 7489b89..0a7a554 100644
> >--- a/drivers/acpi/atomicio.c
> >+++ b/drivers/acpi/atomicio.c
> >@@ -49,6 +49,7 @@ struct acpi_iomap {
> > unsigned long size;
> > phys_addr_t paddr;
> > struct kref ref;
> >+ struct rcu_head iomap_rcu;
> > };
> >
> > /* acpi_iomaps_lock or RCU read lock must be held before calling */
> >@@ -161,6 +162,13 @@ static void __acpi_kref_del_iomap(struct kref *ref)
> > * Used to post-unmap the specified IO memory area. The iounmap is
> > * done only if the reference count goes zero.
> > */
> >+static void acpi_post_unmap_rcu(struct rcu_head *rcu)
> >+{
> >+ struct acpi_iomap *map = container_of(rcu,
> >+ struct acpi_iomap, iomap_rcu);
> >+ iounmap(map->vaddr);
> >+ kfree(map);
> >+}
> > static void acpi_post_unmap(phys_addr_t paddr, unsigned long size)
> > {
> > struct acpi_iomap *map;
> >@@ -176,9 +184,7 @@ static void acpi_post_unmap(phys_addr_t paddr, unsigned long size)
> > if (!del)
> > return;
> >
> >- synchronize_rcu();
> >- iounmap(map->vaddr);
> >- kfree(map);
> >+ call_rcu(&map->iomap_rcu, acpi_post_unmap_rcu);
> > }
> >
> > /* In NMI handler, should set silent = 1 */
> >diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
> >index 372f9b7..9b3a520 100644
> >--- a/drivers/acpi/osl.c
> >+++ b/drivers/acpi/osl.c
> >@@ -105,6 +105,7 @@ struct acpi_ioremap {
> > acpi_physical_address phys;
> > acpi_size size;
> > unsigned long refcount;
> >+ struct rcu_head map_rcu;
> > };
> >
> > static LIST_HEAD(acpi_ioremaps);
> >@@ -373,13 +374,18 @@ static void acpi_os_drop_map_ref(struct acpi_ioremap *map)
> > list_del_rcu(&map->list);
> > }
> >
> >+static void acpi_os_map_cleanup_rcu(struct rcu_head *rcu)
> >+{
> >+ struct acpi_ioremap *map = container_of(rcu,
> >+ struct acpi_ioremap, map_rcu);
> >+ iounmap(map->virt);
> >+ kfree(map);
> >+}
> >+
> > static void acpi_os_map_cleanup(struct acpi_ioremap *map)
> > {
> >- if (!map->refcount) {
> >- synchronize_rcu();
> >- iounmap(map->virt);
> >- kfree(map);
> >- }
> >+ if (!map->refcount)
> >+ call_rcu(&map->map_rcu, acpi_os_map_cleanup_rcu);
> > }
> >
> > void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
>
> Should this be 'UBUNTU: SAUCE:' until its upstreamed (which I think
> is a reasonable thing to do)?
Yes it should.
> Acked-by: Tim Gardner <tim.gardner at canonical.com>
-apw
More information about the kernel-team
mailing list