Skip to contentSkip to conversation

ACPI patch queue for 2.6.39-merge

PATCH In review Len Brown 3 participants 46 messages Mar 23, 2011 – Apr 25, 2011

Subsystems (9)
Documentation x86 ACPI PCI +5 more subsystems
lore
Share & tools
lore

Len Brown

author reviewer
#0 lore raw

Here is my queue for 2.6.39 merge window.
Please speak up if you see problems with any of these patches, or any worthy patches that I missed.

thanks,
Len Brown, Intel Open Source Technology Center

author reviewer
#1 lore raw

PATCH 1/42 ACPI: Do not export functions that are only used in osl.c

From: Rafael J. Wysocki <[email protected]>

The functions acpi_os_map_generic_address() and acpi_os_unmap_generic_address() are only used in drivers/acpi/osl.c, so make them static and remove the extern definitions of them from include/linux/acpi_io.h.

---
 drivers/acpi/osl.c      |    6 ++----
 include/linux/acpi_io.h |    3 ---
 2 files changed, 2 insertions(+), 7 deletions(-)
drivers/acpi/osl.c +2 -4
index c90c76a..ff2189d 100644
@@ -397,7 +397,7 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 		__acpi_unmap_table(virt, size);
 }
 
-int acpi_os_map_generic_address(struct acpi_generic_address *addr)
+static int acpi_os_map_generic_address(struct acpi_generic_address *addr)
 {
 	void __iomem *virt;
 
@@ -413,9 +413,8 @@ int acpi_os_map_generic_address(struct acpi_generic_address *addr)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(acpi_os_map_generic_address);
 
-void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
+static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 {
 	void __iomem *virt;
 	unsigned long flags;
@@ -433,7 +432,6 @@ void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 
 	acpi_os_unmap_memory(virt, size);
 }
-EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address);
 
 #ifdef ACPI_FUTURE_USAGE
 acpi_status
include/linux/acpi_io.h +0 -3
index 7180013..28a3ae2 100644
@@ -10,7 +10,4 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
        return ioremap_cache(phys, size);
 }
 
-int acpi_os_map_generic_address(struct acpi_generic_address *addr);
-void acpi_os_unmap_generic_address(struct acpi_generic_address *addr);
-
 #endif
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#2 lore raw

PATCH 2/42 ACPI: Change acpi_ioremap_lock into a mutex

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

There's no reason why acpi_ioremap_lock has to be a spinlock, because all of the functions it is used in may sleep anyway and there's no reason why it should be locked with interrupts off. Use a mutex instead (that's going to allow us to put some more operations under the lock later).

---
 drivers/acpi/osl.c |   21 +++++++++------------
 1 files changed, 9 insertions(+), 12 deletions(-)
drivers/acpi/osl.c +9 -12
index ff2189d..9706192 100644
@@ -109,7 +109,7 @@ struct acpi_ioremap {
 };
 
 static LIST_HEAD(acpi_ioremaps);
-static DEFINE_SPINLOCK(acpi_ioremap_lock);
+static DEFINE_MUTEX(acpi_ioremap_lock);
 
 static void __init acpi_osi_setup_late(void);
 
@@ -303,7 +303,6 @@ void __iomem *__init_refok
 acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 {
 	struct acpi_ioremap *map, *tmp_map;
-	unsigned long flags;
 	void __iomem *virt;
 	acpi_physical_address pg_off;
 	acpi_size pg_sz;
@@ -334,18 +333,18 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 	map->size = pg_sz;
 	kref_init(&map->ref);
 
-	spin_lock_irqsave(&acpi_ioremap_lock, flags);
+	mutex_lock(&acpi_ioremap_lock);
 	/* 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);
+		mutex_unlock(&acpi_ioremap_lock);
 		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);
+	mutex_unlock(&acpi_ioremap_lock);
 
 	return map->virt + (phys - map->phys);
 }
@@ -362,7 +361,6 @@ static void acpi_kref_del_iomap(struct kref *ref)
 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) {
@@ -370,17 +368,17 @@ void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 		return;
 	}
 
-	spin_lock_irqsave(&acpi_ioremap_lock, flags);
+	mutex_lock(&acpi_ioremap_lock);
 	map = acpi_map_lookup_virt(virt, size);
 	if (!map) {
-		spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+		mutex_unlock(&acpi_ioremap_lock);
 		printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt);
 		dump_stack();
 		return;
 	}
 
 	del = kref_put(&map->ref, acpi_kref_del_iomap);
-	spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+	mutex_unlock(&acpi_ioremap_lock);
 
 	if (!del)
 		return;
@@ -417,7 +415,6 @@ static int acpi_os_map_generic_address(struct acpi_generic_address *addr)
 static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 {
 	void __iomem *virt;
-	unsigned long flags;
 	acpi_size size = addr->bit_width / 8;
 
 	if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
@@ -426,9 +423,9 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 	if (!addr->address || !addr->bit_width)
 		return;
 
-	spin_lock_irqsave(&acpi_ioremap_lock, flags);
+	mutex_lock(&acpi_ioremap_lock);
 	virt = acpi_map_vaddr_lookup(addr->address, size);
-	spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+	mutex_unlock(&acpi_ioremap_lock);
 
 	acpi_os_unmap_memory(virt, size);
 }
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#3 lore raw

PATCH 3/42 ACPI: Avoid walking the list of memory mappings in osl.c twice in a row

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

Make acpi_os_unmap_generic_address() use acpi_map_lookup() to find the desired iomap and drop the reference to it directly (and eventually remove it if necessary) instead of calling acpi_os_unmap_memory(), which requires us to walk the list of ACPI iomaps twice in a row (first, to get the virtual address associated with the iomap and second, to get the iomap itself).

---
 drivers/acpi/osl.c |   33 ++++++++++++++++++++-------------
 1 files changed, 20 insertions(+), 13 deletions(-)
drivers/acpi/osl.c +20 -13
index 9706192..f6785bc 100644
@@ -358,6 +358,13 @@ static void acpi_kref_del_iomap(struct kref *ref)
 	list_del_rcu(&map->list);
 }
 
+static void acpi_os_remove_map(struct acpi_ioremap *map)
+{
+	synchronize_rcu();
+	iounmap(map->virt);
+	kfree(map);
+}
+
 void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 {
 	struct acpi_ioremap *map;
@@ -372,20 +379,14 @@ void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 	map = acpi_map_lookup_virt(virt, size);
 	if (!map) {
 		mutex_unlock(&acpi_ioremap_lock);
-		printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt);
-		dump_stack();
+		WARN(true, PREFIX "%s: bad address %p\n", __func__, virt);
 		return;
 	}
-
 	del = kref_put(&map->ref, acpi_kref_del_iomap);
 	mutex_unlock(&acpi_ioremap_lock);
 
-	if (!del)
-		return;
-
-	synchronize_rcu();
-	iounmap(map->virt);
-	kfree(map);
+	if (del)
+		acpi_os_remove_map(map);
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
 
@@ -414,8 +415,8 @@ static int acpi_os_map_generic_address(struct acpi_generic_address *addr)
 
 static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 {
-	void __iomem *virt;
-	acpi_size size = addr->bit_width / 8;
+	struct acpi_ioremap *map;
+	int del;
 
 	if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
 		return;
@@ -424,10 +425,16 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 		return;
 
 	mutex_lock(&acpi_ioremap_lock);
-	virt = acpi_map_vaddr_lookup(addr->address, size);
+	map = acpi_map_lookup(addr->address, addr->bit_width / 8);
+	if (!map) {
+		mutex_unlock(&acpi_ioremap_lock);
+		return;
+	}
+	del = kref_put(&map->ref, acpi_kref_del_iomap);
 	mutex_unlock(&acpi_ioremap_lock);
 
-	acpi_os_unmap_memory(virt, size);
+	if (del)
+		acpi_os_remove_map(map);
 }
 
 #ifdef ACPI_FUTURE_USAGE
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#4 lore raw

PATCH 4/42 ACPI: Make acpi_os_map_memory() avoid creating unnecessary mappings

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

Modify acpi_os_map_memory() so that it doesn't call acpi_os_ioremap() unconditionally every time it is executed (except when acpi_gbl_permanent_mmap is unset), which pretty much defeats the purpose of maintaining the list of ACPI iomaps in osl.c.

---
 drivers/acpi/osl.c |   28 +++++++++++++++-------------
 1 files changed, 15 insertions(+), 13 deletions(-)
drivers/acpi/osl.c +15 -13
index f6785bc..445f205 100644
@@ -302,7 +302,7 @@ 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, *tmp_map;
+	struct acpi_ioremap *map;
 	void __iomem *virt;
 	acpi_physical_address pg_off;
 	acpi_size pg_sz;
@@ -315,14 +315,25 @@ 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) {
+		kref_get(&map->ref);
+		goto out;
+	}
+
 	map = kzalloc(sizeof(*map), GFP_KERNEL);
-	if (!map)
+	if (!map) {
+		mutex_unlock(&acpi_ioremap_lock);
 		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;
 	}
@@ -333,19 +344,10 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 	map->size = pg_sz;
 	kref_init(&map->ref);
 
-	mutex_lock(&acpi_ioremap_lock);
-	/* Check if page has already been mapped. */
-	tmp_map = acpi_map_lookup(phys, size);
-	if (tmp_map) {
-		kref_get(&tmp_map->ref);
-		mutex_unlock(&acpi_ioremap_lock);
-		iounmap(map->virt);
-		kfree(map);
-		return tmp_map->virt + (phys - tmp_map->phys);
-	}
 	list_add_tail_rcu(&map->list, &acpi_ioremaps);
-	mutex_unlock(&acpi_ioremap_lock);
 
+ out:
+	mutex_unlock(&acpi_ioremap_lock);
 	return map->virt + (phys - map->phys);
 }
 EXPORT_SYMBOL_GPL(acpi_os_map_memory);
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#5 lore raw

PATCH 5/42 ACPI: Do not use krefs under a mutex in osl.c

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

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.

---
 drivers/acpi/osl.c |   36 ++++++++++++++++--------------------
 1 files changed, 16 insertions(+), 20 deletions(-)
drivers/acpi/osl.c +16 -20
index 445f205..5389f9f 100644
@@ -105,7 +105,7 @@ struct acpi_ioremap {
 	void __iomem *virt;
 	acpi_physical_address phys;
 	acpi_size size;
-	struct kref ref;
+	unsigned long refcount;
 };
 
 static LIST_HEAD(acpi_ioremaps);
@@ -319,7 +319,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 	/* Check if there's a suitable mapping already. */
 	map = acpi_map_lookup(phys, size);
 	if (map) {
-		kref_get(&map->ref);
+		map->refcount++;
 		goto out;
 	}
 
@@ -342,7 +342,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 	map->virt = virt;
 	map->phys = pg_off;
 	map->size = pg_sz;
-	kref_init(&map->ref);
+	map->refcount = 1;
 
 	list_add_tail_rcu(&map->list, &acpi_ioremaps);
 
@@ -352,25 +352,24 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 }
 EXPORT_SYMBOL_GPL(acpi_os_map_memory);
 
-static void acpi_kref_del_iomap(struct kref *ref)
+static void acpi_os_drop_map_ref(struct acpi_ioremap *map)
 {
-	struct acpi_ioremap *map;
-
-	map = container_of(ref, struct acpi_ioremap, ref);
-	list_del_rcu(&map->list);
+	if (!--map->refcount)
+		list_del_rcu(&map->list);
 }
 
-static void acpi_os_remove_map(struct acpi_ioremap *map)
+static void acpi_os_map_cleanup(struct acpi_ioremap *map)
 {
-	synchronize_rcu();
-	iounmap(map->virt);
-	kfree(map);
+	if (!map->refcount) {
+		synchronize_rcu();
+		iounmap(map->virt);
+		kfree(map);
+	}
 }
 
 void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 {
 	struct acpi_ioremap *map;
-	int del;
 
 	if (!acpi_gbl_permanent_mmap) {
 		__acpi_unmap_table(virt, size);
@@ -384,11 +383,10 @@ void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 		WARN(true, PREFIX "%s: bad address %p\n", __func__, virt);
 		return;
 	}
-	del = kref_put(&map->ref, acpi_kref_del_iomap);
+	acpi_os_drop_map_ref(map);
 	mutex_unlock(&acpi_ioremap_lock);
 
-	if (del)
-		acpi_os_remove_map(map);
+	acpi_os_map_cleanup(map);
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
 
@@ -418,7 +416,6 @@ static int acpi_os_map_generic_address(struct acpi_generic_address *addr)
 static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 {
 	struct acpi_ioremap *map;
-	int del;
 
 	if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
 		return;
@@ -432,11 +429,10 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 		mutex_unlock(&acpi_ioremap_lock);
 		return;
 	}
-	del = kref_put(&map->ref, acpi_kref_del_iomap);
+	acpi_os_drop_map_ref(map);
 	mutex_unlock(&acpi_ioremap_lock);
 
-	if (del)
-		acpi_os_remove_map(map);
+	acpi_os_map_cleanup(map);
 }
 
 #ifdef ACPI_FUTURE_USAGE
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#6 lore raw

PATCH 6/42 ACPI: Introduce acpi_os_get_iomem()

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

Introduce function acpi_os_get_iomem() that may be used by its callers to get a reference to an ACPI iomap.

---
 drivers/acpi/osl.c      |   16 ++++++++++++++++
 include/linux/acpi_io.h |    2 ++
 2 files changed, 18 insertions(+), 0 deletions(-)
drivers/acpi/osl.c +16 -0
index 5389f9f..52ca872 100644
@@ -285,6 +285,22 @@ 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)
include/linux/acpi_io.h +2 -0
index 28a3ae2..4afd710 100644
@@ -10,4 +10,6 @@ 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);
+
 #endif
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#7 lore raw

PATCH 7/42 ACPI / PM: Use existing ACPI iomaps for NVS save/restore (v2)

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

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.

---
 drivers/acpi/nvs.c |   22 +++++++++++++++++++---
 1 files changed, 19 insertions(+), 3 deletions(-)
drivers/acpi/nvs.c +19 -3
index fa5a1df..096787b 100644
@@ -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;
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#8 lore raw

PATCH 8/42 ACPI: Remove the wakeup.run_wake_count device field

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

The wakeup.run_wake_count ACPI device field is only used by the PCI runtime PM code to "protect" devices from being prepared for generating wakeup signals more than once in a row. However, it really doesn't provide any protection, because (1) all of the functions it is supposed to protect use their own reference counters effectively ensuring that the device will be set up for generating wakeup signals just once and (2) the PCI runtime PM code uses wakeup.run_wake_count in a racy way, since nothing prevents acpi_dev_run_wake() from being called concurrently from two different threads for the same device.

Remove the wakeup.run_wake_count ACPI device field which is unnecessary, confusing and used in a wrong way.

---
 drivers/acpi/button.c   |    2 --
 drivers/acpi/scan.c     |    1 -
 drivers/pci/pci-acpi.c  |   16 ++++------------
 include/acpi/acpi_bus.h |    1 -
 4 files changed, 4 insertions(+), 16 deletions(-)
drivers/acpi/button.c +0 -2
index 76bbb78..e643a09 100644
@@ -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);
 	}
 
drivers/acpi/scan.c +0 -1
index b99e624..b136c9c 100644
@@ -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 */
drivers/pci/pci-acpi.c +4 -12
index 6fe0772..7c3b18e 100644
@@ -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;
include/acpi/acpi_bus.h +0 -1
index 78ca429..f50ebb9 100644
@@ -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 */
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#9 lore raw

PATCH 9/42 ACPI / Button: Avoid disabling wakeup unnecessarily on remove

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

If a button device had already been enabled to wake up the system from sleep states before the button driver saw it, the driver shouldn't disable the device's wakeup capability when being detached from the device.

---
 drivers/acpi/button.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)
drivers/acpi/button.c +7 -2
index e643a09..12c28f4 100644
@@ -98,6 +98,7 @@ struct acpi_button {
 	struct input_dev *input;
 	char phys[32];			/* for input device */
 	unsigned long pushed;
+	bool wakeup_enabled;
 };
 
 static const struct file_operations acpi_button_info_fops = {
@@ -430,7 +431,10 @@ 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_set_wakeup_enable(&device->dev, true);
+		if (!device_may_wakeup(&device->dev)) {
+			device_set_wakeup_enable(&device->dev, true);
+			button->wakeup_enabled = true;
+		}
 	}
 
 	printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
@@ -452,7 +456,8 @@ 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_set_wakeup_enable(&device->dev, false);
+		if (button->wakeup_enabled)
+			device_set_wakeup_enable(&device->dev, false);
 	}
 
 	acpi_button_remove_fs(device);
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#10 lore raw

PATCH 10/42 ACPI / PM: Drop acpi_restore_state_mem()

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

The function acpi_restore_state_mem() has never been and most likely never will be used, so remove it.

---
 arch/ia64/include/asm/acpi.h |    4 ++--
 arch/ia64/kernel/acpi.c      |    5 -----
 arch/x86/include/asm/acpi.h  |    3 +--
 arch/x86/kernel/acpi/sleep.c |    8 --------
 drivers/acpi/sleep.c         |    4 ----
 5 files changed, 3 insertions(+), 21 deletions(-)
arch/ia64/include/asm/acpi.h +2 -2
index 837dc82..db3986a 100644
@@ -128,9 +128,9 @@ static inline const char *acpi_get_sysname (void)
 int acpi_request_vector (u32 int_type);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
-/* routines for saving/restoring kernel state */
+/* Routine for saving kernel state during suspend. */
 extern int acpi_save_state_mem(void);
-extern void acpi_restore_state_mem(void);
+
 extern unsigned long acpi_wakeup_address;
 
 /*
arch/ia64/kernel/acpi.c +0 -5
index 90ebceb..7cf2d10 100644
@@ -1041,11 +1041,6 @@ EXPORT_SYMBOL(acpi_unregister_ioapic);
 int acpi_save_state_mem(void) { return 0; } 
 
 /*
- * acpi_restore_state()
- */
-void acpi_restore_state_mem(void) {}
-
-/*
  * do_suspend_lowlevel()
  */
 void do_suspend_lowlevel(void) {}
arch/x86/include/asm/acpi.h +1 -2
index 211ca3f..47981f0 100644
@@ -112,9 +112,8 @@ static inline void acpi_disable_pci(void)
 	acpi_noirq_set();
 }
 
-/* routines for saving/restoring kernel state */
+/* Routine for saving kernel state during suspend. */
 extern int acpi_save_state_mem(void);
-extern void acpi_restore_state_mem(void);
 
 extern unsigned long acpi_wakeup_address;
 
arch/x86/kernel/acpi/sleep.c +0 -8
index 68d1537..c27a483 100644
@@ -110,14 +110,6 @@ int acpi_save_state_mem(void)
 	return 0;
 }
 
-/*
- * acpi_restore_state - undo effects of acpi_save_state_mem
- */
-void acpi_restore_state_mem(void)
-{
-}
-
-
 /**
  * acpi_reserve_wakeup_memory - do _very_ early ACPI initialisation
  *
drivers/acpi/sleep.c +0 -4
index d6a8cd1..67dcd38 100644
@@ -293,10 +293,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 	local_irq_restore(flags);
 	printk(KERN_DEBUG "Back to C!\n");
 
-	/* restore processor state */
-	if (acpi_state == ACPI_STATE_S3)
-		acpi_restore_state_mem();
-
 	suspend_nvs_restore();
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#11 lore raw

PATCH 11/42 ACPI / PM: acpi_suspend_enter() need not switch interrupts off

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

The function acpi_suspend_enter() is always called with interrupts off, so it doesn't need to switch them off and on.

---
 drivers/acpi/sleep.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)
drivers/acpi/sleep.c +0 -3
index 67dcd38..3b54937 100644
@@ -243,7 +243,6 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
 static int acpi_suspend_enter(suspend_state_t pm_state)
 {
 	acpi_status status = AE_OK;
-	unsigned long flags = 0;
 	u32 acpi_state = acpi_target_sleep_state;
 
 	ACPI_FLUSH_CPU_CACHE();
@@ -256,7 +255,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 			return error;
 	}
 
-	local_irq_save(flags);
 	switch (acpi_state) {
 	case ACPI_STATE_S1:
 		barrier();
@@ -290,7 +288,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 	/* Allow EC transactions to happen. */
 	acpi_ec_unblock_transactions_early();
 
-	local_irq_restore(flags);
 	printk(KERN_DEBUG "Back to C!\n");
 
 	suspend_nvs_restore();
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#12 lore raw

PATCH 12/42 ACPI / PM: Modify the "low-level resume finished" message

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

Move the low-level resume completion message to the point where control goes back to acpi_suspend_enter() during resume and change it so that it's more informative.

---
 drivers/acpi/sleep.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)
drivers/acpi/sleep.c +1 -2
index 3b54937..6bea2fe 100644
@@ -263,6 +263,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 
 	case ACPI_STATE_S3:
 		do_suspend_lowlevel();
+		pr_info(PREFIX "Low-level resume complete\n");
 		break;
 	}
 
@@ -288,8 +289,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 	/* Allow EC transactions to happen. */
 	acpi_ec_unblock_transactions_early();
 
-	printk(KERN_DEBUG "Back to C!\n");
-
 	suspend_nvs_restore();
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#13 lore raw

PATCH 13/42 ACPI / PM: Call acpi_save_state_mem() right before low-level suspend

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

Since acpi_save_state_mem() is only called by acpi_suspend_enter() if the target sleep state is S3, it's better to call it under the switch (acpi_state), right before do_suspend_lowlevel().

---
 drivers/acpi/sleep.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)
drivers/acpi/sleep.c +4 -8
index 6bea2fe..2307604 100644
@@ -244,17 +244,10 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 {
 	acpi_status status = AE_OK;
 	u32 acpi_state = acpi_target_sleep_state;
+	int error;
 
 	ACPI_FLUSH_CPU_CACHE();
 
-	/* Do arch specific saving of state. */
-	if (acpi_state == ACPI_STATE_S3) {
-		int error = acpi_save_state_mem();
-
-		if (error)
-			return error;
-	}
-
 	switch (acpi_state) {
 	case ACPI_STATE_S1:
 		barrier();
@@ -262,6 +255,9 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 		break;
 
 	case ACPI_STATE_S3:
+		error = acpi_save_state_mem();
+		if (error)
+			return error;
 		do_suspend_lowlevel();
 		pr_info(PREFIX "Low-level resume complete\n");
 		break;
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#14 lore raw

PATCH 14/42 ACPI / PM: Merge do_suspend_lowlevel() into acpi_save_state_mem()

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

The function do_suspend_lowlevel() is specific to x86 and defined in assembly code, so it should be called from the x86 low-level suspend code rather than from acpi_suspend_enter().

Merge do_suspend_lowlevel() into the x86's acpi_save_state_mem() and change the name of the latter to acpi_suspend_lowlevel(), so that the function's purpose is better reflected by its name.

---
 arch/ia64/include/asm/acpi.h |    4 ++--
 arch/ia64/kernel/acpi.c      |    9 ++-------
 arch/x86/include/asm/acpi.h  |    4 ++--
 arch/x86/kernel/acpi/sleep.c |    5 +++--
 arch/x86/kernel/acpi/sleep.h |    2 ++
 drivers/acpi/sleep.c         |    5 +----
 6 files changed, 12 insertions(+), 17 deletions(-)
arch/ia64/include/asm/acpi.h +2 -2
index db3986a..a06dfb1 100644
@@ -128,8 +128,8 @@ static inline const char *acpi_get_sysname (void)
 int acpi_request_vector (u32 int_type);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
-/* Routine for saving kernel state during suspend. */
-extern int acpi_save_state_mem(void);
+/* Low-level suspend routine. */
+extern int acpi_suspend_lowlevel(void);
 
 extern unsigned long acpi_wakeup_address;
 
arch/ia64/kernel/acpi.c +2 -7
index 7cf2d10..a54d054 100644
@@ -1034,13 +1034,8 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
 /*
- * acpi_save_state_mem() - save kernel state
+ * acpi_suspend_lowlevel() - save kernel state and suspend.
  *
  * TBD when when IA64 starts to support suspend...
  */
-int acpi_save_state_mem(void) { return 0; } 
-
-/*
- * do_suspend_lowlevel()
- */
-void do_suspend_lowlevel(void) {}
+int acpi_suspend_lowlevel(void) { return 0; }
arch/x86/include/asm/acpi.h +2 -2
index 47981f0..aa92684 100644
@@ -112,8 +112,8 @@ static inline void acpi_disable_pci(void)
 	acpi_noirq_set();
 }
 
-/* Routine for saving kernel state during suspend. */
-extern int acpi_save_state_mem(void);
+/* Low-level suspend routine. */
+extern int acpi_suspend_lowlevel(void);
 
 extern unsigned long acpi_wakeup_address;
 
arch/x86/kernel/acpi/sleep.c +3 -2
index c27a483..5f1b747 100644
@@ -29,14 +29,14 @@ static char temp_stack[4096];
 #endif
 
 /**
- * acpi_save_state_mem - save kernel state
+ * acpi_suspend_lowlevel - save kernel state
  *
  * Create an identity mapped page table and copy the wakeup routine to
  * low memory.
  *
  * Note that this is too late to change acpi_wakeup_address.
  */
-int acpi_save_state_mem(void)
+int acpi_suspend_lowlevel(void)
 {
 	struct wakeup_header *header;
 
@@ -107,6 +107,7 @@ int acpi_save_state_mem(void)
        saved_magic = 0x123456789abcdef0L;
 #endif /* CONFIG_64BIT */
 
+	do_suspend_lowlevel();
 	return 0;
 }
 
arch/x86/kernel/acpi/sleep.h +2 -0
index adbcbaa..31ce13f 100644
@@ -14,3 +14,5 @@ extern char swsusp_pg_dir[PAGE_SIZE];
 
 extern unsigned long acpi_copy_wakeup_routine(unsigned long);
 extern void wakeup_long64(void);
+
+extern void do_suspend_lowlevel(void);
drivers/acpi/sleep.c +1 -4
index 2307604..0a81bf1 100644
@@ -199,8 +199,6 @@ static void acpi_pm_end(void)
 #endif /* CONFIG_ACPI_SLEEP */
 
 #ifdef CONFIG_SUSPEND
-extern void do_suspend_lowlevel(void);
-
 static u32 acpi_suspend_states[] = {
 	[PM_SUSPEND_ON] = ACPI_STATE_S0,
 	[PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
@@ -255,10 +253,9 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 		break;
 
 	case ACPI_STATE_S3:
-		error = acpi_save_state_mem();
+		error = acpi_suspend_lowlevel();
 		if (error)
 			return error;
-		do_suspend_lowlevel();
 		pr_info(PREFIX "Low-level resume complete\n");
 		break;
 	}
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#15 lore raw

PATCH 15/42 ACPI / PM: acpi_hibernation_enter() need not switch interrupts off

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

The function acpi_hibernation_enter() is always called with interrupts off, so it doesn't need to switch them off and on.

---
 drivers/acpi/sleep.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)
drivers/acpi/sleep.c +0 -3
index 0a81bf1..84f5714 100644
@@ -457,16 +457,13 @@ static int acpi_hibernation_begin(void)
 static int acpi_hibernation_enter(void)
 {
 	acpi_status status = AE_OK;
-	unsigned long flags = 0;
 
 	ACPI_FLUSH_CPU_CACHE();
 
-	local_irq_save(flags);
 	/* This shouldn't return.  If it returns, we have a problem */
 	status = acpi_enter_sleep_state(ACPI_STATE_S4);
 	/* Reprogram control registers and execute _BFS */
 	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
-	local_irq_restore(flags);
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
 }
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#16 lore raw

PATCH 16/42 ACPI: Avoid calling request_irq() many times for the same interrupt

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

In principle acpi_os_install_interrupt_handler() may be called multiple times for different interrupts, either from acpi_ev_get_gpe_xrupt_block(), or from acpi_ev_install_sci_handler(). However, it always attempts to request the same interrupt, acpi_gbl_FADT.sci_interrupt and it doesn't check whether or not this interrupt has already been requested.

Modify this function so that it refuses to request interrupts other than acpi_gbl_FADT.sci_interrupt and change acpi_os_remove_interrupt_handler() so that it refuses to free such interrupts. Use the observation that the only supported ACPI interrupt must be equal to acpi_gbl_FADT.sci_interrupt and drop an unnecessary variable acpi_irq_irq.

This change has been tested on Toshiba Portege R500 and HP nx6325 without introducing any visible problems.

---
 drivers/acpi/osl.c |   27 +++++++++++++++------------
 1 files changed, 15 insertions(+), 12 deletions(-)
drivers/acpi/osl.c +15 -12
index c90c76a..187dff9 100644
@@ -76,7 +76,6 @@ EXPORT_SYMBOL(acpi_in_debugger);
 extern char line_buf[80];
 #endif				/*ENABLE_DEBUGGER */
 
-static unsigned int acpi_irq_irq;
 static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
@@ -516,11 +515,15 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
 	acpi_irq_stats_init();
 
 	/*
-	 * Ignore the GSI from the core, and use the value in our copy of the
-	 * FADT. It may not be the same if an interrupt source override exists
-	 * for the SCI.
+	 * ACPI interrupts different from the SCI in our copy of the FADT are
+	 * not supported.
 	 */
-	gsi = acpi_gbl_FADT.sci_interrupt;
+	if (gsi != acpi_gbl_FADT.sci_interrupt)
+		return AE_BAD_PARAMETER;
+
+	if (acpi_irq_handler)
+		return AE_ALREADY_ACQUIRED;
+
 	if (acpi_gsi_to_irq(gsi, &irq) < 0) {
 		printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
 		       gsi);
@@ -531,20 +534,20 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
 	acpi_irq_context = context;
 	if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
 		printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
+		acpi_irq_handler = NULL;
 		return AE_NOT_ACQUIRED;
 	}
-	acpi_irq_irq = irq;
 
 	return AE_OK;
 }
 
 acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
 {
-	if (irq) {
-		free_irq(irq, acpi_irq);
-		acpi_irq_handler = NULL;
-		acpi_irq_irq = 0;
-	}
+	if (irq != acpi_gbl_FADT.sci_interrupt)
+		return AE_BAD_PARAMETER;
+
+	free_irq(irq, acpi_irq);
+	acpi_irq_handler = NULL;
 
 	return AE_OK;
 }
@@ -1603,7 +1606,7 @@ acpi_status __init acpi_os_initialize1(void)
 acpi_status acpi_os_terminate(void)
 {
 	if (acpi_irq_handler) {
-		acpi_os_remove_interrupt_handler(acpi_irq_irq,
+		acpi_os_remove_interrupt_handler(acpi_gbl_FADT.sci_interrupt,
 						 acpi_irq_handler);
 	}
 
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#17 lore raw

PATCH 17/42 ACPICA: GPE detect optimization - ignore unused GPE registers

In reply to Len Brown

From: Lin Ming <[email protected]>

This optimization will simply ignore GPE registers that contain no enabled GPEs - there is no need to read the register. ACPICA bugzilla 884.

http://www.acpica.org/bugzilla/show_bug.cgi?id=884

---
 drivers/acpi/acpica/evgpe.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)
drivers/acpi/acpica/evgpe.c +9 -0
index 14988a8..67d44ef 100644
@@ -373,6 +373,15 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 
 			gpe_register_info = &gpe_block->register_info[i];
 
+			/*
+			 * Optimization: If there are no GPEs enabled within this
+			 * register, we can safely ignore the entire register.
+			 */
+			if (!(gpe_register_info->enable_for_run |
+			      gpe_register_info->enable_for_wake)) {
+				continue;
+			}
+
 			/* Read the Status Register */
 
 			status =
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#18 lore raw

PATCH 18/42 ACPICA: Remove use of unreliable FADT revision field

In reply to Len Brown

From: Bob Moore <[email protected]>

The revision number in the FADT has been found to be completely unreliable and cannot be trusted. Only the table length can be used to infer the actual version.

---
 drivers/acpi/acpica/tbfadt.c |    5 ++++-
 include/acpi/actbl.h         |   16 ++++++++++++++++
 2 files changed, 20 insertions(+), 1 deletions(-)
drivers/acpi/acpica/tbfadt.c +4 -1
index 428d44e..6f5588e 100644
@@ -384,8 +384,11 @@ static void acpi_tb_convert_fadt(void)
 	 *
 	 * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at
 	 * offset 45, 55, 95, and the word located at offset 109, 110.
+	 *
+	 * Note: The FADT revision value is unreliable. Only the length can be
+	 * trusted.
 	 */
-	if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) {
+	if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) {
 		acpi_gbl_FADT.preferred_profile = 0;
 		acpi_gbl_FADT.pstate_control = 0;
 		acpi_gbl_FADT.cst_control = 0;
include/acpi/actbl.h +16 -0
index 7e42bfe..d41c948 100644
@@ -343,4 +343,20 @@ struct acpi_table_desc {
 #include <acpi/actbl1.h>
 #include <acpi/actbl2.h>
 
+/*
+ * Sizes of the various flavors of FADT. We need to look closely
+ * at the FADT length because the version number essentially tells
+ * us nothing because of many BIOS bugs where the version does not
+ * match the expected length. In other words, the length of the
+ * FADT is the bottom line as to what the version really is.
+ *
+ * For reference, the values below are as follows:
+ *     FADT V1  size: 0x74
+ *     FADT V2  size: 0x84
+ *     FADT V3+ size: 0xF4
+ */
+#define ACPI_FADT_V1_SIZE       (u32) (ACPI_FADT_OFFSET (flags) + 4)
+#define ACPI_FADT_V2_SIZE       (u32) (ACPI_FADT_OFFSET (reserved4[0]) + 3)
+#define ACPI_FADT_V3_SIZE       (u32) (sizeof (struct acpi_table_fadt))
+
 #endif				/* __ACTBL_H__ */
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#19 lore raw

PATCH 19/42 ACPICA: Clarify a couple of error messages

In reply to Len Brown

From: Bob Moore <[email protected]>

Clarify region error messages with ID= prefix for space id.

---
 drivers/acpi/acpica/exfldio.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/acpi/acpica/exfldio.c +2 -2
index 6c79c29..f915a7f 100644
@@ -280,13 +280,13 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
 	if (ACPI_FAILURE(status)) {
 		if (status == AE_NOT_IMPLEMENTED) {
 			ACPI_ERROR((AE_INFO,
-				    "Region %s(0x%X) not implemented",
+				    "Region %s (ID=%u) not implemented",
 				    acpi_ut_get_region_name(rgn_desc->region.
 							    space_id),
 				    rgn_desc->region.space_id));
 		} else if (status == AE_NOT_EXIST) {
 			ACPI_ERROR((AE_INFO,
-				    "Region %s(0x%X) has no handler",
+				    "Region %s (ID=%u) has no handler",
 				    acpi_ut_get_region_name(rgn_desc->region.
 							    space_id),
 				    rgn_desc->region.space_id));
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#20 lore raw

PATCH 20/42 ACPICA: Split large utglobal into utdecode.c.

In reply to Len Brown

From: Bob Moore <[email protected]>

utglobal.c contained a lot of code not related to global variables. These utility decode functions are moved to utdecode.c

---
 drivers/acpi/acpica/Makefile   |    2 +-
 drivers/acpi/acpica/aclocal.h  |   19 --
 drivers/acpi/acpica/utdecode.c |  546 ++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/acpica/utglobal.c |  483 -----------------------------------
 4 files changed, 547 insertions(+), 503 deletions(-)
 create mode 100644 drivers/acpi/acpica/utdecode.c
drivers/acpi/acpica/Makefile +1 -1
index eec2ead..b1706aa 100644
@@ -45,4 +45,4 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
 acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
 		utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
 		utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \
-		utosi.o utxferror.o
+		utosi.o utxferror.o utdecode.o
drivers/acpi/acpica/aclocal.h +0 -19
index 54784bb..01bcab1 100644
@@ -89,25 +89,6 @@ union acpi_parse_object;
 #define ACPI_MAX_MUTEX                  7
 #define ACPI_NUM_MUTEX                  ACPI_MAX_MUTEX+1
 
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
-#ifdef DEFINE_ACPI_GLOBALS
-
-/* Debug names for the mutexes above */
-
-static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
-	"ACPI_MTX_Interpreter",
-	"ACPI_MTX_Namespace",
-	"ACPI_MTX_Tables",
-	"ACPI_MTX_Events",
-	"ACPI_MTX_Caches",
-	"ACPI_MTX_Memory",
-	"ACPI_MTX_CommandComplete",
-	"ACPI_MTX_CommandReady"
-};
-
-#endif
-#endif
-
 /* Lock structure for reader/writer interfaces */
 
 struct acpi_rw_lock {
drivers/acpi/acpica/utdecode.c new file +546 -0

546 lines not on this page · raw message

drivers/acpi/acpica/utglobal.c +0 -483

507 lines not on this page · raw message

Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#21 lore raw

PATCH 21/42 ACPICA: Fix unresolved name issue for no-debug and no-error-msg cases

In reply to Len Brown

From: Bob Moore <[email protected]>

The _acpi_module_name was left undefined in these cases, but it is actually needed as a parameter to some interfaces. Define _acpi_module_name as a null string in these cases. Acpica BZ 888.

http://www.acpica.org/bugzilla/show_bug.cgi?id=888

---
 include/acpi/acoutput.h |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)
include/acpi/acoutput.h +9 -3
index ef1cef7..d7bd661 100644
@@ -183,13 +183,19 @@
 
 #if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES)
 /*
- * Module name is included in both debug and non-debug versions primarily for
- * error messages. The __FILE__ macro is not very useful for this, because it
- * often includes the entire pathname to the module
+ * The module name is used primarily for error and debug messages.
+ * The __FILE__ macro is not very useful for this, because it
+ * usually includes the entire pathname to the module making the
+ * debug output difficult to read.
  */
 #define ACPI_MODULE_NAME(name)          static const char ACPI_UNUSED_VAR _acpi_module_name[] = name;
 #else
+/*
+ * For the no-debug and no-error-msg cases, we must at least define
+ * a null module name.
+ */
 #define ACPI_MODULE_NAME(name)
+#define _acpi_module_name ""
 #endif
 
 /*
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#22 lore raw

PATCH 22/42 ACPICA: Split large dsopcode and dsload.c files.

In reply to Len Brown

From: Bob Moore <[email protected]>

Split dsopcode.c into dsargs.c and dscontrol.c.
Split dsload.c into dsload2.c.

---
 drivers/acpi/acpica/Makefile    |    2 +-
 drivers/acpi/acpica/acdispat.h  |   38 ++-
 drivers/acpi/acpica/dsargs.c    |  391 +++++++++++++++++++++
 drivers/acpi/acpica/dscontrol.c |  410 ++++++++++++++++++++++
 drivers/acpi/acpica/dsopcode.c  |  725 +--------------------------------------
 drivers/acpi/acpica/dswload.c   |  670 +------------------------------------
 drivers/acpi/acpica/dswload2.c  |  720 ++++++++++++++++++++++++++++++++++++++
 7 files changed, 1549 insertions(+), 1407 deletions(-)
 create mode 100644 drivers/acpi/acpica/dsargs.c
 create mode 100644 drivers/acpi/acpica/dscontrol.c
 create mode 100644 drivers/acpi/acpica/dswload2.c
drivers/acpi/acpica/Makefile +1 -1
index b1706aa..a122471 100644
@@ -10,7 +10,7 @@ obj-y	+= acpi.o
 
 acpi-y := dsfield.o   dsmthdat.o  dsopcode.o  dswexec.o  dswscope.o \
 	 dsmethod.o  dsobject.o  dsutils.o   dswload.o  dswstate.o \
-	 dsinit.o
+	 dsinit.o dsargs.o dscontrol.o dswload2.o
 
 acpi-y += evevent.o  evregion.o  evsci.o    evxfevnt.o \
 	 evmisc.o   evrgnini.o  evxface.o  evxfregn.o \
drivers/acpi/acpica/acdispat.h +22 -16
index 666271b..2d1b7ff 100644
@@ -48,7 +48,7 @@
 #define NAMEOF_ARG_NTE      "__A0"
 
 /*
- * dsopcode - support for late evaluation
+ * dsargs - execution of dynamic arguments for static objects
  */
 acpi_status
 acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc);
@@ -62,6 +62,20 @@ acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc);
 
 acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc);
 
+/*
+ * dscontrol - support for execution control opcodes
+ */
+acpi_status
+acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
+			      union acpi_parse_object *op);
+
+acpi_status
+acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
+			    union acpi_parse_object *op);
+
+/*
+ * dsopcode - support for late operand evaluation
+ */
 acpi_status
 acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
 				   union acpi_parse_object *op);
@@ -86,17 +100,6 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
 acpi_status acpi_ds_initialize_region(acpi_handle obj_handle);
 
 /*
- * dsctrl - Parser/Interpreter interface, control stack routines
- */
-acpi_status
-acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
-			      union acpi_parse_object *op);
-
-acpi_status
-acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
-			    union acpi_parse_object *op);
-
-/*
  * dsexec - Parser/Interpreter interface, method execution callbacks
  */
 acpi_status
@@ -136,23 +139,26 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
 			   struct acpi_walk_state *walk_state);
 
 /*
- * dsload - Parser/Interpreter interface, namespace load callbacks
+ * dsload - Parser/Interpreter interface, pass 1 namespace load callbacks
  */
 acpi_status
+acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number);
+
+acpi_status
 acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,
 		       union acpi_parse_object **out_op);
 
 acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state);
 
+/*
+ * dsload - Parser/Interpreter interface, pass 2 namespace load callbacks
+ */
 acpi_status
 acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
 		       union acpi_parse_object **out_op);
 
 acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state);
 
-acpi_status
-acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number);
-
 /*
  * dsmthdat - method data (locals/args)
  */
drivers/acpi/acpica/dsargs.c new file +391 -0

391 lines not on this page · raw message

drivers/acpi/acpica/dscontrol.c new file +410 -0

410 lines not on this page · raw message

drivers/acpi/acpica/dsopcode.c +4 -721

751 lines not on this page · raw message

drivers/acpi/acpica/dswload.c +1 -669

684 lines not on this page · raw message

drivers/acpi/acpica/dswload2.c new file +720 -0

681 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.7.4.1.343.ga91df

Part of the diff is not shown here. View the raw message.

author reviewer
#23 lore raw

PATCH 23/42 ACPICA: Add support for FunctionalFixedHW in acpi_ut_get_region_name

In reply to Len Brown

From: Bob Moore <[email protected]>

Was missing this region type.

---
 drivers/acpi/acpica/utdecode.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/acpi/acpica/utdecode.c +2 -0
index ce91e59..136a814 100644
@@ -179,6 +179,8 @@ char *acpi_ut_get_region_name(u8 space_id)
 
 	if (space_id >= ACPI_USER_REGION_BEGIN) {
 		return ("UserDefinedRegion");
+	} else if (space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
+		return ("FunctionalFixedHW");
 	} else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) {
 		return ("InvalidSpaceId");
 	}
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#24 lore raw

PATCH 24/42 ACPICA: Add mechanism to defer _REG methods for some installed handlers

In reply to Len Brown

From: Bob Moore <[email protected]>

The memory/io/pci/dataTable regions must always be available. For any user installed handlers for these spaces, defer execution of _REG methods until acpi_enable_subsystem. This prevents any chicken/egg problems and ensures that no methods are executed until all of these regions are ready and available.

---
 drivers/acpi/acpica/acglobal.h |    4 ++++
 drivers/acpi/acpica/evregion.c |    2 ++
 drivers/acpi/acpica/evxfregn.c |   36 +++++++++++++++++++++++++++++++++---
 drivers/acpi/acpica/utglobal.c |    1 +
 4 files changed, 40 insertions(+), 3 deletions(-)
drivers/acpi/acpica/acglobal.h +4 -0
index 82a1bd2..d69750b 100644
@@ -273,6 +273,10 @@ ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS];
 ACPI_EXTERN u8 acpi_gbl_last_owner_id_index;
 ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset;
 
+/* Initialization sequencing */
+
+ACPI_EXTERN u8 acpi_gbl_reg_methods_executed;
+
 /* Misc */
 
 ACPI_EXTERN u32 acpi_gbl_original_mode;
drivers/acpi/acpica/evregion.c +2 -0
index 785a5ee..bea7223 100644
@@ -231,6 +231,8 @@ acpi_status acpi_ev_initialize_op_regions(void)
 		}
 	}
 
+	acpi_gbl_reg_methods_executed = TRUE;
+
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return_ACPI_STATUS(status);
 }
drivers/acpi/acpica/evxfregn.c +32 -2
index eb73867..c85c8c4 100644
@@ -110,9 +110,39 @@ acpi_install_address_space_handler(acpi_handle device,
 		goto unlock_and_exit;
 	}
 
-	/* Run all _REG methods for this address space */
+	/*
+	 * For the default space_iDs, (the IDs for which there are default region handlers
+	 * installed) Only execute the _REG methods if the global initialization _REG
+	 * methods have already been run (via acpi_initialize_objects). In other words,
+	 * we will defer the execution of the _REG methods for these space_iDs until
+	 * execution of acpi_initialize_objects. This is done because we need the handlers
+	 * for the default spaces (mem/io/pci/table) to be installed before we can run
+	 * any control methods (or _REG methods). There is known BIOS code that depends
+	 * on this.
+	 *
+	 * For all other space_iDs, we can safely execute the _REG methods immediately.
+	 * This means that for IDs like embedded_controller, this function should be called
+	 * only after acpi_enable_subsystem has been called.
+	 */
+	switch (space_id) {
+	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+	case ACPI_ADR_SPACE_SYSTEM_IO:
+	case ACPI_ADR_SPACE_PCI_CONFIG:
+	case ACPI_ADR_SPACE_DATA_TABLE:
+
+		if (acpi_gbl_reg_methods_executed) {
+
+			/* Run all _REG methods for this address space */
+
+			status = acpi_ev_execute_reg_methods(node, space_id);
+		}
+		break;
+
+	default:
 
-	status = acpi_ev_execute_reg_methods(node, space_id);
+		status = acpi_ev_execute_reg_methods(node, space_id);
+		break;
+	}
 
       unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
drivers/acpi/acpica/utglobal.c +1 -0
index fc90978..833a38a 100644
@@ -323,6 +323,7 @@ acpi_status acpi_ut_init_globals(void)
 	acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
 	acpi_gbl_osi_data = 0;
 	acpi_gbl_osi_mutex = NULL;
+	acpi_gbl_reg_methods_executed = FALSE;
 
 	/* Hardware oriented */
 
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#25 lore raw

PATCH 25/42 ACPICA: Update version to 20110211.

In reply to Len Brown

From: Bob Moore <[email protected]>

Version 20110211.

---
 include/acpi/acpixf.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/acpi/acpixf.h +1 -1
index e46ec95..ec90854 100644
@@ -47,7 +47,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20110112
+#define ACPI_CA_VERSION                 0x20110211
 
 #include "actypes.h"
 #include "actbl.h"
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#26 lore raw

PATCH 26/42 Thermal_Framework-Fix_crash_during_hwmon_unregister

In reply to Len Brown

From: Durgadoss R <[email protected]>

This patch fixes the following bug:
The thermal framework creates a temp*_crit interface, only when the get_crit_temp pointer is defined. But during the _unregister_ path, without checking for the function definition, it is trying to remove the temp*_crit interface.

---
 drivers/thermal/thermal_sys.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/thermal/thermal_sys.c +2 -1
index 713b7ea..fc6f2a5 100644
@@ -560,7 +560,8 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
 
 	tz->hwmon = NULL;
 	device_remove_file(hwmon->device, &tz->temp_input.attr);
-	device_remove_file(hwmon->device, &tz->temp_crit.attr);
+	if (tz->ops->get_crit_temp)
+		device_remove_file(hwmon->device, &tz->temp_crit.attr);
 
 	mutex_lock(&thermal_list_lock);
 	list_del(&tz->hwmon_node);
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#27 lore raw

PATCH 27/42 ACPI: use __init where possible in processor driver

In reply to Len Brown

From: Jan Beulich <[email protected]>

Use __init for several functions, remove an unnecessary export and a stray use of __ref.

---
 drivers/acpi/processor_core.c   |    9 ++++-----
 drivers/acpi/processor_driver.c |    4 ++--
 2 files changed, 6 insertions(+), 7 deletions(-)
drivers/acpi/processor_core.c +4 -5
index 3c1a2fe..ac77dde 100644
@@ -19,7 +19,7 @@
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_core");
 
-static int set_no_mwait(const struct dmi_system_id *id)
+static int __init set_no_mwait(const struct dmi_system_id *id)
 {
 	printk(KERN_NOTICE PREFIX "%s detected - "
 		"disabling mwait for CPU C-states\n", id->ident);
@@ -27,7 +27,7 @@ static int set_no_mwait(const struct dmi_system_id *id)
 	return 0;
 }
 
-static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
+static struct dmi_system_id __initdata processor_idle_dmi_table[] = {
 	{
 	set_no_mwait, "Extensa 5220", {
 	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
@@ -183,7 +183,7 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
 EXPORT_SYMBOL_GPL(acpi_get_cpuid);
 #endif
 
-static bool processor_physically_present(acpi_handle handle)
+static bool __init processor_physically_present(acpi_handle handle)
 {
 	int cpuid, type;
 	u32 acpi_id;
@@ -323,9 +323,8 @@ void acpi_processor_set_pdc(acpi_handle handle)
 	kfree(obj_list->pointer);
 	kfree(obj_list);
 }
-EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
 
-static acpi_status
+static acpi_status __init
 early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
 	if (processor_physically_present(handle) == false)
drivers/acpi/processor_driver.c +2 -2
index 360a74e..a4e0f1b 100644
@@ -635,8 +635,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
 	return 0;
 }
 
-static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
-						u32 event, void *data)
+static void acpi_processor_hotplug_notify(acpi_handle handle,
+					  u32 event, void *data)
 {
 	struct acpi_processor *pr;
 	struct acpi_device *device = NULL;
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#28 lore raw

PATCH 28/42 ACPI: use __cpuinit for the acpi_processor_set_pdc() call tree

In reply to Len Brown

From: Jan Beulich <[email protected]>

Once acpi_map_lsapic() in ia64 follows how x86 treats it wrt section placement, the whole tree from acpi_processor_set_pdc() can become __cpuinit.

---
 arch/ia64/kernel/acpi.c       |    9 +++++++--
 drivers/acpi/processor_core.c |    8 ++++----
 2 files changed, 11 insertions(+), 6 deletions(-)
arch/ia64/kernel/acpi.c +7 -2
index 90ebceb..522642d 100644
@@ -803,7 +803,7 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
  *  ACPI based hotplug CPU support
  */
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
-static
+static __cpuinit
 int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 {
 #ifdef CONFIG_ACPI_NUMA
@@ -878,7 +878,7 @@ __init void prefill_possible_map(void)
 		set_cpu_possible(i, true);
 }
 
-int acpi_map_lsapic(acpi_handle handle, int *pcpu)
+static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *obj;
@@ -929,6 +929,11 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
 	return (0);
 }
 
+/* wrapper to silence section mismatch warning */
+int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+{
+	return _acpi_map_lsapic(handle, pcpu);
+}
 EXPORT_SYMBOL(acpi_map_lsapic);
 
 int acpi_unmap_lsapic(int cpu)
drivers/acpi/processor_core.c +4 -4
index ac77dde..25bf17d 100644
@@ -223,7 +223,7 @@ static bool __init processor_physically_present(acpi_handle handle)
 	return true;
 }
 
-static void acpi_set_pdc_bits(u32 *buf)
+static void __cpuinit acpi_set_pdc_bits(u32 *buf)
 {
 	buf[0] = ACPI_PDC_REVISION_ID;
 	buf[1] = 1;
@@ -235,7 +235,7 @@ static void acpi_set_pdc_bits(u32 *buf)
 	arch_acpi_set_pdc_bits(buf);
 }
 
-static struct acpi_object_list *acpi_processor_alloc_pdc(void)
+static struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void)
 {
 	struct acpi_object_list *obj_list;
 	union acpi_object *obj;
@@ -278,7 +278,7 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void)
  * _PDC is required for a BIOS-OS handshake for most of the newer
  * ACPI processor features.
  */
-static int
+static int __cpuinit
 acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
 {
 	acpi_status status = AE_OK;
@@ -306,7 +306,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
 	return status;
 }
 
-void acpi_processor_set_pdc(acpi_handle handle)
+void __cpuinit acpi_processor_set_pdc(acpi_handle handle)
 {
 	struct acpi_object_list *obj_list;
 
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#29 lore raw

PATCH 29/42 ACPI: Remove the unused EC sysdev class

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

The ACPI EC driver defines a sysdev class, but it doesn't use it, so it can be removed.

---
 drivers/acpi/ec_sys.c   |    4 ----
 drivers/acpi/internal.h |    3 ---
 2 files changed, 0 insertions(+), 7 deletions(-)
drivers/acpi/ec_sys.c +0 -4
index 411620e..05b4420 100644
@@ -24,10 +24,6 @@ MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may "
 
 #define EC_SPACE_SIZE 256
 
-struct sysdev_class acpi_ec_sysdev_class = {
-	.name = "ec",
-};
-
 static struct dentry *acpi_ec_debugfs_dir;
 
 static int acpi_ec_open_io(struct inode *i, struct file *f)
drivers/acpi/internal.h +0 -3
index b1cc81a..4bfb759 100644
@@ -21,8 +21,6 @@
 #ifndef _ACPI_INTERNAL_H_
 #define _ACPI_INTERNAL_H_
 
-#include <linux/sysdev.h>
-
 #define PREFIX "ACPI: "
 
 int init_acpi_device_notify(void);
@@ -64,7 +62,6 @@ struct acpi_ec {
 	struct list_head list;
 	struct transaction *curr;
 	spinlock_t curr_lock;
-	struct sys_device sysdev;
 };
 
 extern struct acpi_ec *first_ec;
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#30 lore raw

PATCH 30/42 ACPI: Use syscore_ops instead of sysdev class and sysdev

In reply to Len Brown

From: Rafael J. Wysocki <[email protected]>

ACPI uses a sysdev class and a sysdev for executing irqrouter_resume() before turning on interrupts on the boot CPU. However, since irqrouter_resume() ignores its argument, the entire mechanism may be replaced with a struct syscore_ops object which is considerably simpler.

---
 drivers/acpi/pci_link.c |   30 ++++++++----------------------
 1 files changed, 8 insertions(+), 22 deletions(-)
drivers/acpi/pci_link.c +8 -22
index 9ff80a7..4a29763 100644
@@ -29,7 +29,7 @@
  *	   for IRQ management (e.g. start()->_SRS).
  */
 
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -757,14 +757,13 @@ static int acpi_pci_link_resume(struct acpi_pci_link *link)
 	return 0;
 }
 
-static int irqrouter_resume(struct sys_device *dev)
+static void irqrouter_resume(void)
 {
 	struct acpi_pci_link *link;
 
 	list_for_each_entry(link, &acpi_link_list, list) {
 		acpi_pci_link_resume(link);
 	}
-	return 0;
 }
 
 static int acpi_pci_link_remove(struct acpi_device *device, int type)
@@ -871,32 +870,19 @@ static int __init acpi_irq_balance_set(char *str)
 
 __setup("acpi_irq_balance", acpi_irq_balance_set);
 
-/* FIXME: we will remove this interface after all drivers call pci_disable_device */
-static struct sysdev_class irqrouter_sysdev_class = {
-	.name = "irqrouter",
+static struct syscore_ops irqrouter_syscore_ops = {
 	.resume = irqrouter_resume,
 };
 
-static struct sys_device device_irqrouter = {
-	.id = 0,
-	.cls = &irqrouter_sysdev_class,
-};
-
-static int __init irqrouter_init_sysfs(void)
+static int __init irqrouter_init_ops(void)
 {
-	int error;
+	if (!acpi_disabled && !acpi_noirq)
+		register_syscore_ops(&irqrouter_syscore_ops);
 
-	if (acpi_disabled || acpi_noirq)
-		return 0;
-
-	error = sysdev_class_register(&irqrouter_sysdev_class);
-	if (!error)
-		error = sysdev_register(&device_irqrouter);
-
-	return error;
+	return 0;
 }
 
-device_initcall(irqrouter_init_sysfs);
+device_initcall(irqrouter_init_ops);
 
 static int __init acpi_pci_link_init(void)
 {
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#31 lore raw

PATCH 31/42 ACPI, APEI, Add ERST record ID cache

In reply to Len Brown

From: Huang Ying <[email protected]>

APEI ERST firmware interface and implementation has no multiple users in mind. For example, if there is four records in storage with ID: 1, 2, 3 and 4, if two ERST readers enumerate the records via GET_NEXT_RECORD_ID as follow,

reader 1 reader 2
1

			2
3
			4
-1
			-1

where -1 signals there is no more record ID.

Reader 1 has no chance to check record 2 and 4, while reader 2 has no chance to check record 1 and 3. And any other GET_NEXT_RECORD_ID will return -1, that is, other readers will has no chance to check any record even they are not cleared by anyone.

This makes raw GET_NEXT_RECORD_ID not suitable for used by multiple users.

To solve the issue, an in-memory ERST record ID cache is designed and implemented. When enumerating record ID, the ID returned by GET_NEXT_RECORD_ID is added into cache in addition to be returned to caller. So other readers can check the cache to get all record ID available.

---
 arch/x86/kernel/cpu/mcheck/mce-apei.c |   42 ++++---
 drivers/acpi/apei/erst-dbg.c          |   24 +++-
 drivers/acpi/apei/erst.c              |  235 ++++++++++++++++++++++++++------
 include/acpi/apei.h                   |    5 +-
 4 files changed, 241 insertions(+), 65 deletions(-)
arch/x86/kernel/cpu/mcheck/mce-apei.c +26 -16
index 8209472..83930de 100644
@@ -106,24 +106,34 @@ int apei_write_mce(struct mce *m)
 ssize_t apei_read_mce(struct mce *m, u64 *record_id)
 {
 	struct cper_mce_record rcd;
-	ssize_t len;
-
-	len = erst_read_next(&rcd.hdr, sizeof(rcd));
-	if (len <= 0)
-		return len;
-	/* Can not skip other records in storage via ERST unless clear them */
-	else if (len != sizeof(rcd) ||
-		 uuid_le_cmp(rcd.hdr.creator_id, CPER_CREATOR_MCE)) {
-		if (printk_ratelimit())
-			pr_warning(
-			"MCE-APEI: Can not skip the unknown record in ERST");
-		return -EIO;
-	}
-
+	int rc, pos;
+
+	rc = erst_get_record_id_begin(&pos);
+	if (rc)
+		return rc;
+retry:
+	rc = erst_get_record_id_next(&pos, record_id);
+	if (rc)
+		goto out;
+	/* no more record */
+	if (*record_id == APEI_ERST_INVALID_RECORD_ID)
+		goto out;
+	rc = erst_read(*record_id, &rcd.hdr, sizeof(rcd));
+	/* someone else has cleared the record, try next one */
+	if (rc == -ENOENT)
+		goto retry;
+	else if (rc < 0)
+		goto out;
+	/* try to skip other type records in storage */
+	else if (rc != sizeof(rcd) ||
+		 uuid_le_cmp(rcd.hdr.creator_id, CPER_CREATOR_MCE))
+		goto retry;
 	memcpy(m, &rcd.mce, sizeof(*m));
-	*record_id = rcd.hdr.record_id;
+	rc = sizeof(*m);
+out:
+	erst_get_record_id_end();
 
-	return sizeof(*m);
+	return rc;
 }
 
 /* Check whether there is record in ERST */
drivers/acpi/apei/erst-dbg.c +21 -3
index de73caf..a4cfb64 100644
@@ -43,12 +43,27 @@ static DEFINE_MUTEX(erst_dbg_mutex);
 
 static int erst_dbg_open(struct inode *inode, struct file *file)
 {
+	int rc, *pos;
+
 	if (erst_disable)
 		return -ENODEV;
 
+	pos = (int *)&file->private_data;
+
+	rc = erst_get_record_id_begin(pos);
+	if (rc)
+		return rc;
+
 	return nonseekable_open(inode, file);
 }
 
+static int erst_dbg_release(struct inode *inode, struct file *file)
+{
+	erst_get_record_id_end();
+
+	return 0;
+}
+
 static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
 	int rc;
@@ -79,18 +94,20 @@ static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf,
 			     size_t usize, loff_t *off)
 {
-	int rc;
+	int rc, *pos;
 	ssize_t len = 0;
 	u64 id;
 
-	if (*off != 0)
+	if (*off)
 		return -EINVAL;
 
 	if (mutex_lock_interruptible(&erst_dbg_mutex) != 0)
 		return -EINTR;
 
+	pos = (int *)&filp->private_data;
+
 retry_next:
-	rc = erst_get_next_record_id(&id);
+	rc = erst_get_record_id_next(pos, &id);
 	if (rc)
 		goto out;
 	/* no more record */
@@ -181,6 +198,7 @@ out:
 static const struct file_operations erst_dbg_ops = {
 	.owner		= THIS_MODULE,
 	.open		= erst_dbg_open,
+	.release	= erst_dbg_release,
 	.read		= erst_dbg_read,
 	.write		= erst_dbg_write,
 	.unlocked_ioctl	= erst_dbg_ioctl,
drivers/acpi/apei/erst.c +191 -44

279 lines not on this page · raw message

include/acpi/apei.h +3 -2
index c4dbb13..e67b523 100644
@@ -30,10 +30,11 @@ int apei_hest_parse(apei_hest_func_t func, void *data);
 
 int erst_write(const struct cper_record_header *record);
 ssize_t erst_get_record_count(void);
-int erst_get_next_record_id(u64 *record_id);
+int erst_get_record_id_begin(int *pos);
+int erst_get_record_id_next(int *pos, u64 *record_id);
+void erst_get_record_id_end(void);
 ssize_t erst_read(u64 record_id, struct cper_record_header *record,
 		  size_t buflen);
-ssize_t erst_read_next(struct cper_record_header *record, size_t buflen);
 int erst_clear(u64 record_id);
 
 #endif
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#32 lore raw

PATCH 32/42 PCIe, AER, use pre-generated prefix in error information printing

In reply to Len Brown

From: Huang Ying <[email protected]>

When printing PCIe AER error information, each line is prefixed with PCIe device and driver information. In original implementation, the prefix is generated when each line is printed. In fact, all lines share the same prefix. So this patch pre-generated the prefix, and use that one when each line is printed.

In addition to common prefix can be pre-generated, the trailing white spaces in string constants and NULLs in char * array constants can be removed too. These can reduce the object file size further.

The size of object file before and after changing is as follow:

text data bss dec

before:    3038       0       0    3038
after:     2118       0       0    2118
---
 drivers/pci/pcie/aer/aerdrv_errprint.c |  123 ++++++++++++-------------------
 1 files changed, 48 insertions(+), 75 deletions(-)
drivers/pci/pcie/aer/aerdrv_errprint.c +48 -75
index 9d3e4c8..7a237f6 100644
@@ -57,86 +57,44 @@
 	(e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \
 	AER_TRANSACTION_LAYER_ERROR)
 
-#define AER_PR(info, pdev, fmt, args...)				\
-	printk("%s%s %s: " fmt, (info->severity == AER_CORRECTABLE) ?	\
-		KERN_WARNING : KERN_ERR, dev_driver_string(&pdev->dev),	\
-		dev_name(&pdev->dev), ## args)
-
 /*
  * AER error strings
  */
-static char *aer_error_severity_string[] = {
+static const char *aer_error_severity_string[] = {
 	"Uncorrected (Non-Fatal)",
 	"Uncorrected (Fatal)",
 	"Corrected"
 };
 
-static char *aer_error_layer[] = {
+static const char *aer_error_layer[] = {
 	"Physical Layer",
 	"Data Link Layer",
 	"Transaction Layer"
 };
-static char *aer_correctable_error_string[] = {
-	"Receiver Error        ",	/* Bit Position 0	*/
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Bad TLP               ",	/* Bit Position 6	*/
-	"Bad DLLP              ",	/* Bit Position 7	*/
-	"RELAY_NUM Rollover    ",	/* Bit Position 8	*/
-	NULL,
-	NULL,
-	NULL,
-	"Replay Timer Timeout  ",	/* Bit Position 12	*/
-	"Advisory Non-Fatal    ",	/* Bit Position 13	*/
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
+
+static const char *aer_correctable_error_string[] = {
+	"Receiver Error",		/* Bit Position 0	*/
 	NULL,
 	NULL,
 	NULL,
 	NULL,
 	NULL,
+	"Bad TLP",			/* Bit Position 6	*/
+	"Bad DLLP",			/* Bit Position 7	*/
+	"RELAY_NUM Rollover",		/* Bit Position 8	*/
 	NULL,
 	NULL,
 	NULL,
+	"Replay Timer Timeout",		/* Bit Position 12	*/
+	"Advisory Non-Fatal",		/* Bit Position 13	*/
 };
 
-static char *aer_uncorrectable_error_string[] = {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Data Link Protocol    ",	/* Bit Position 4	*/
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Poisoned TLP          ",	/* Bit Position 12	*/
-	"Flow Control Protocol ",	/* Bit Position 13	*/
-	"Completion Timeout    ",	/* Bit Position 14	*/
-	"Completer Abort       ",	/* Bit Position 15	*/
-	"Unexpected Completion ",	/* Bit Position 16	*/
-	"Receiver Overflow     ",	/* Bit Position 17	*/
-	"Malformed TLP         ",	/* Bit Position 18	*/
-	"ECRC                  ",	/* Bit Position 19	*/
-	"Unsupported Request   ",	/* Bit Position 20	*/
+static const char *aer_uncorrectable_error_string[] = {
 	NULL,
 	NULL,
 	NULL,
 	NULL,
+	"Data Link Protocol",		/* Bit Position 4	*/
 	NULL,
 	NULL,
 	NULL,
@@ -144,19 +102,29 @@ static char *aer_uncorrectable_error_string[] = {
 	NULL,
 	NULL,
 	NULL,
+	"Poisoned TLP",			/* Bit Position 12	*/
+	"Flow Control Protocol",	/* Bit Position 13	*/
+	"Completion Timeout",		/* Bit Position 14	*/
+	"Completer Abort",		/* Bit Position 15	*/
+	"Unexpected Completion",	/* Bit Position 16	*/
+	"Receiver Overflow",		/* Bit Position 17	*/
+	"Malformed TLP",		/* Bit Position 18	*/
+	"ECRC",				/* Bit Position 19	*/
+	"Unsupported Request",		/* Bit Position 20	*/
 };
 
-static char *aer_agent_string[] = {
+static const char *aer_agent_string[] = {
 	"Receiver ID",
 	"Requester ID",
 	"Completer ID",
 	"Transmitter ID"
 };
 
-static void __aer_print_error(struct aer_err_info *info, struct pci_dev *dev)
+static void __aer_print_error(const char *prefix,
+			      struct aer_err_info *info)
 {
 	int i, status;
-	char *errmsg = NULL;
+	const char *errmsg = NULL;
 
 	status = (info->status & ~info->mask);
 
@@ -165,15 +133,17 @@ static void __aer_print_error(struct aer_err_info *info, struct pci_dev *dev)
 			continue;
 
 		if (info->severity == AER_CORRECTABLE)
-			errmsg = aer_correctable_error_string[i];
+			errmsg = i < ARRAY_SIZE(aer_correctable_error_string) ?
+				aer_correctable_error_string[i] : NULL;
 		else
-			errmsg = aer_uncorrectable_error_string[i];
+			errmsg = i < ARRAY_SIZE(aer_uncorrectable_error_string) ?
+				aer_uncorrectable_error_string[i] : NULL;
 
 		if (errmsg)
-			AER_PR(info, dev, "   [%2d] %s%s\n", i, errmsg,
+			printk("%s""   [%2d] %-22s%s\n", prefix, i, errmsg,
 				info->first_error == i ? " (First)" : "");
 		else
-			AER_PR(info, dev, "   [%2d] Unknown Error Bit%s\n", i,
+			printk("%s""   [%2d] Unknown Error Bit%s\n", prefix, i,
 				info->first_error == i ? " (First)" : "");
 	}
 }
@@ -181,11 +151,15 @@ static void __aer_print_error(struct aer_err_info *info, struct pci_dev *dev)
 void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
 {
 	int id = ((dev->bus->number << 8) | dev->devfn);
+	char prefix[44];
+
+	snprintf(prefix, sizeof(prefix), "%s%s %s: ",
+		 (info->severity == AER_CORRECTABLE) ? KERN_WARNING : KERN_ERR,
+		 dev_driver_string(&dev->dev), dev_name(&dev->dev));
 
 	if (info->status == 0) {
-		AER_PR(info, dev,
-			"PCIe Bus Error: severity=%s, type=Unaccessible, "
-			"id=%04x(Unregistered Agent ID)\n",
+		printk("%s""PCIe Bus Error: severity=%s, type=Unaccessible, "
+			"id=%04x(Unregistered Agent ID)\n", prefix,
 			aer_error_severity_string[info->severity], id);
 	} else {
 		int layer, agent;
@@ -193,23 +167,22 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
 		layer = AER_GET_LAYER_ERROR(info->severity, info->status);
 		agent = AER_GET_AGENT(info->severity, info->status);
 
-		AER_PR(info, dev,
-			"PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
-			aer_error_severity_string[info->severity],
+		printk("%s""PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
+			prefix, aer_error_severity_string[info->severity],
 			aer_error_layer[layer], id, aer_agent_string[agent]);
 
-		AER_PR(info, dev,
-			"  device [%04x:%04x] error status/mask=%08x/%08x\n",
-			dev->vendor, dev->device, info->status, info->mask);
+		printk("%s""  device [%04x:%04x] error status/mask=%08x/%08x\n",
+			prefix, dev->vendor, dev->device,
+			info->status, info->mask);
 
-		__aer_print_error(info, dev);
+		__aer_print_error(prefix, info);
 
 		if (info->tlp_header_valid) {
 			unsigned char *tlp = (unsigned char *) &info->tlp;
-			AER_PR(info, dev, "  TLP Header:"
+			printk("%s""  TLP Header:"
 				" %02x%02x%02x%02x %02x%02x%02x%02x"
 				" %02x%02x%02x%02x %02x%02x%02x%02x\n",
-				*(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+				prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
 				*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
 				*(tlp + 11), *(tlp + 10), *(tlp + 9),
 				*(tlp + 8), *(tlp + 15), *(tlp + 14),
@@ -218,8 +191,8 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
 	}
 
 	if (info->id && info->error_dev_num > 1 && info->id == id)
-		AER_PR(info, dev,
-			"  Error of this Agent(%04x) is reported first\n", id);
+		printk("%s""  Error of this Agent(%04x) is reported first\n",
+			prefix, id);
 }
 
 void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#33 lore raw

PATCH 33/42 ACPI, APEI, Add PCIe AER error information printing support

In reply to Len Brown

From: Huang Ying <[email protected]>

The AER error information printing support is implemented in drivers/pci/pcie/aer/aer_print.c. So some string constants, functions and macros definitions can be re-used without being exported.

The original PCIe AER error information printing function is not re-used directly because the overall format is quite different. And changing the original printing format may make some original users' scripts broken.

---
 Documentation/acpi/apei/output_format.txt |   25 ++++++++++++
 drivers/acpi/apei/Kconfig                 |    7 +++
 drivers/acpi/apei/cper.c                  |   18 +++++++--
 drivers/pci/pcie/aer/aerdrv.h             |    9 +----
 drivers/pci/pcie/aer/aerdrv_errprint.c    |   59 +++++++++++++++++++++++++++++
 include/linux/aer.h                       |   24 ++++++++++++
 include/linux/cper.h                      |    2 +
 7 files changed, 132 insertions(+), 12 deletions(-)
Documentation/acpi/apei/output_format.txt +25 -0
index 9146952..0c49c19 100644
@@ -92,6 +92,11 @@ vendor_id: <integer>, device_id: <integer>
 class_code: <integer>]
 [serial number: <integer>, <integer>]
 [bridge: secondary_status: <integer>, control: <integer>]
+[aer_status: <integer>, aer_mask: <integer>
+<aer status string>
+[aer_uncor_severity: <integer>]
+aer_layer=<aer layer string>, aer_agent=<aer agent string>
+aer_tlp_header: <integer> <integer> <integer> <integer>]
 
 <pcie port type string>* := PCIe end point | legacy PCI end point | \
 unknown | unknown | root port | upstream switch port | \
@@ -99,6 +104,26 @@ downstream switch port | PCIe to PCI/PCI-X bridge | \
 PCI/PCI-X to PCIe bridge | root complex integrated endpoint device | \
 root complex event collector
 
+if section severity is fatal or recoverable
+<aer status string># :=
+unknown | unknown | unknown | unknown | Data Link Protocol | \
+unknown | unknown | unknown | unknown | unknown | unknown | unknown | \
+Poisoned TLP | Flow Control Protocol | Completion Timeout | \
+Completer Abort | Unexpected Completion | Receiver Overflow | \
+Malformed TLP | ECRC | Unsupported Request
+else
+<aer status string># :=
+Receiver Error | unknown | unknown | unknown | unknown | unknown | \
+Bad TLP | Bad DLLP | RELAY_NUM Rollover | unknown | unknown | unknown | \
+Replay Timer Timeout | Advisory Non-Fatal
+fi
+
+<aer layer string> :=
+Physical Layer | Data Link Layer | Transaction Layer
+
+<aer agent string> :=
+Receiver ID | Requester ID | Completer ID | Transmitter ID
+
 Where, [] designate corresponding content is optional
 
 All <field string> description with * has the following format:
drivers/acpi/apei/Kconfig +7 -0
index fca34cc..9ecf6fe 100644
@@ -21,6 +21,13 @@ config ACPI_APEI_GHES
 	  by firmware to produce more valuable hardware error
 	  information for Linux.
 
+config ACPI_APEI_PCIEAER
+	bool "APEI PCIe AER logging/recovering support"
+	depends on ACPI_APEI && PCIEAER
+	help
+	  PCIe AER errors may be reported via APEI firmware first mode.
+	  Turn on this option to enable the corresponding support.
+
 config ACPI_APEI_EINJ
 	tristate "APEI Error INJection (EINJ)"
 	depends on ACPI_APEI && DEBUG_FS
drivers/acpi/apei/cper.c +14 -4
index 31464a0..5d41894 100644
@@ -29,6 +29,7 @@
 #include <linux/time.h>
 #include <linux/cper.h>
 #include <linux/acpi.h>
+#include <linux/aer.h>
 
 /*
  * CPER record ID need to be unique even after reboot, because record
@@ -70,8 +71,8 @@ static const char *cper_severity_str(unsigned int severity)
  * If the output length is longer than 80, multiple line will be
  * printed, with @pfx is printed at the beginning of each line.
  */
-static void cper_print_bits(const char *pfx, unsigned int bits,
-			    const char *strs[], unsigned int strs_size)
+void cper_print_bits(const char *pfx, unsigned int bits,
+		     const char *strs[], unsigned int strs_size)
 {
 	int i, len = 0;
 	const char *str;
@@ -81,6 +82,8 @@ static void cper_print_bits(const char *pfx, unsigned int bits,
 		if (!(bits & (1U << i)))
 			continue;
 		str = strs[i];
+		if (!str)
+			continue;
 		if (len && len + strlen(str) + 2 > 80) {
 			printk("%s\n", buf);
 			len = 0;
@@ -243,7 +246,8 @@ static const char *cper_pcie_port_type_strs[] = {
 	"root complex event collector",
 };
 
-static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie)
+static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
+			    const struct acpi_hest_generic_data *gdata)
 {
 	if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
 		printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
@@ -276,6 +280,12 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie)
 		printk(
 	"%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
 	pfx, pcie->bridge.secondary_status, pcie->bridge.control);
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+	if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) {
+		struct aer_capability_regs *aer_regs = (void *)pcie->aer_info;
+		cper_print_aer(pfx, gdata->error_severity, aer_regs);
+	}
+#endif
 }
 
 static const char *apei_estatus_section_flag_strs[] = {
@@ -322,7 +332,7 @@ static void apei_estatus_print_section(
 		struct cper_sec_pcie *pcie = (void *)(gdata + 1);
 		printk("%s""section_type: PCIe error\n", pfx);
 		if (gdata->error_data_length >= sizeof(*pcie))
-			cper_print_pcie(pfx, pcie);
+			cper_print_pcie(pfx, pcie, gdata);
 		else
 			goto err_section_too_small;
 	} else
drivers/pci/pcie/aer/aerdrv.h +1 -8
index 80c11d1..3eb7708 100644
@@ -35,13 +35,6 @@
 					PCI_ERR_UNC_UNX_COMP|		\
 					PCI_ERR_UNC_MALF_TLP)
 
-struct header_log_regs {
-	unsigned int dw0;
-	unsigned int dw1;
-	unsigned int dw2;
-	unsigned int dw3;
-};
-
 #define AER_MAX_MULTI_ERR_DEVICES	5	/* Not likely to have more */
 struct aer_err_info {
 	struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
@@ -59,7 +52,7 @@ struct aer_err_info {
 
 	unsigned int status;		/* COR/UNCOR Error Status */
 	unsigned int mask;		/* COR/UNCOR Error Mask */
-	struct header_log_regs tlp;	/* TLP Header */
+	struct aer_header_log_regs tlp;	/* TLP Header */
 };
 
 struct aer_err_source {
drivers/pci/pcie/aer/aerdrv_errprint.c +59 -0

68 lines not on this page · raw message

include/linux/aer.h +24 -0
index f7df1ee..8414de2 100644
@@ -7,6 +7,28 @@
 #ifndef _AER_H_
 #define _AER_H_
 
+struct aer_header_log_regs {
+	unsigned int dw0;
+	unsigned int dw1;
+	unsigned int dw2;
+	unsigned int dw3;
+};
+
+struct aer_capability_regs {
+	u32 header;
+	u32 uncor_status;
+	u32 uncor_mask;
+	u32 uncor_severity;
+	u32 cor_status;
+	u32 cor_mask;
+	u32 cap_control;
+	struct aer_header_log_regs header_log;
+	u32 root_command;
+	u32 root_status;
+	u16 cor_err_source;
+	u16 uncor_err_source;
+};
+
 #if defined(CONFIG_PCIEAER)
 /* pci-e port driver needs this function to enable aer */
 extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
@@ -27,5 +49,7 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
 }
 #endif
 
+extern void cper_print_aer(const char *prefix, int cper_severity,
+			   struct aer_capability_regs *aer);
 #endif //_AER_H_
 
include/linux/cper.h +2 -0
index 3104aaf..372a258 100644
@@ -388,5 +388,7 @@ struct cper_sec_pcie {
 #pragma pack()
 
 u64 cper_next_record_id(void);
+void cper_print_bits(const char *prefix, unsigned int bits,
+		     const char *strs[], unsigned int strs_size);
 
 #endif
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#34 lore raw

PATCH 34/42 ACPI button: remove unused procfs I/F

In reply to Len Brown

From: Zhang Rui <[email protected]>

Remove unused ACPI button procfs interface.
Only /proc/acpi/button/lid/LID/state remains.

---
 Documentation/feature-removal-schedule.txt |    8 --
 drivers/acpi/button.c                      |  163 ++++++++++------------------
 2 files changed, 60 insertions(+), 111 deletions(-)
Documentation/feature-removal-schedule.txt +0 -8
index b3f35e5..e461525 100644
@@ -259,14 +259,6 @@ Who:	Zhang Rui <[email protected]>
 
 ---------------------------
 
-What:	/proc/acpi/button
-When:	August 2007
-Why:	/proc/acpi/button has been replaced by events to the input layer
-	since 2.6.20.
-Who:	Len Brown <[email protected]>
-
----------------------------
-
 What:	/proc/acpi/event
 When:	February 2008
 Why:	/proc/acpi/event has been replaced by events via the input layer
drivers/acpi/button.c +60 -103

219 lines not on this page · raw message

Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#35 lore raw

PATCH 35/42 ACPI battery: fribble sysfs files from a resume notifier

In reply to Len Brown

From: Kyle McMartin <[email protected]>

Commit da8aeb92 re-poked the battery on resume, but Linus reports that it broke his eee and partially reverted it in b23fffd7. Unfortunately this also results in my x201s giving crack values until the sysfs files are poked again. In the revert message, it was suggested that we poke it from a PM notifier, so let's do that.

With this in place, I haven't noticed the units going nutty on my gnome-power-manager across a dozen suspends or so...

---
 drivers/acpi/battery.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)
drivers/acpi/battery.c +22 -0
index ac1a599..fcc13ac 100644
@@ -33,6 +33,7 @@
 #include <linux/async.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <linux/suspend.h>
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 #include <linux/proc_fs.h>
@@ -102,6 +103,7 @@ struct acpi_battery {
 	struct mutex lock;
 	struct power_supply bat;
 	struct acpi_device *device;
+	struct notifier_block pm_nb;
 	unsigned long update_time;
 	int rate_now;
 	int capacity_now;
@@ -940,6 +942,21 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
 		power_supply_changed(&battery->bat);
 }
 
+static int battery_notify(struct notifier_block *nb,
+			       unsigned long mode, void *_unused)
+{
+	struct acpi_battery *battery = container_of(nb, struct acpi_battery,
+						    pm_nb);
+	switch (mode) {
+	case PM_POST_SUSPEND:
+		sysfs_remove_battery(battery);
+		sysfs_add_battery(battery);
+		break;
+	}
+
+	return 0;
+}
+
 static int acpi_battery_add(struct acpi_device *device)
 {
 	int result = 0;
@@ -972,6 +989,10 @@ static int acpi_battery_add(struct acpi_device *device)
 #endif
 		kfree(battery);
 	}
+
+	battery->pm_nb.notifier_call = battery_notify;
+	register_pm_notifier(&battery->pm_nb);
+
 	return result;
 }
 
@@ -982,6 +1003,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
 	battery = acpi_driver_data(device);
+	unregister_pm_notifier(&battery->pm_nb);
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	acpi_battery_remove_fs(device);
 #endif
Signature · 1 line
1.7.4.1.343.ga91df
#37 lore raw

Re: [PATCH 35/42] ACPI battery: fribble sysfs files from a resume notifier

In reply to Len Brown

Len,

Do we think this has baked enough for stable 2.6.38.3? I'd like to drop the patch from Fedora when we pull the next stable update in.

Greg -- this is upstream commit
25be5821521640eb00b7eb219ffe59664510d073.

regards, Kyle

Quoted 14 lines · Len Brown

From: Kyle McMartin <[email protected]>

Commit da8aeb92 re-poked the battery on resume, but Linus reports that it broke his eee and partially reverted it in b23fffd7. Unfortunately this also results in my x201s giving crack values until the sysfs files are poked again. In the revert message, it was suggested that we poke it from a PM notifier, so let's do that.

With this in place, I haven't noticed the units going nutty on my gnome-power-manager across a dozen suspends or so...

#38 lore raw

Re: [stable] [PATCH 35/42] ACPI battery: fribble sysfs files from a resume notifier

Quoted 7 lines · Kyle McMartin

Len,

Do we think this has baked enough for stable 2.6.38.3? I'd like to drop the patch from Fedora when we pull the next stable update in.

Greg -- this is upstream commit
25be5821521640eb00b7eb219ffe59664510d073.

Ok, now queued up, thanks.

greg k-h

author reviewer
#39 lore raw

PATCH 36/42 ACPICA: Fix access width for reset vector

In reply to Len Brown

From: Matthew Garrett <[email protected]>

Section 4.7.3.6 of the ACPI specification requires that the register width of the reset vector be 8 bits. Windows simply hardcodes the access to be a byte and ignores the width provided in the FADT, so make sure that we do the same.

---
 drivers/acpi/acpica/hwxface.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)
drivers/acpi/acpica/hwxface.c +5 -5
index 6f98d21..f75f81a 100644
@@ -80,14 +80,14 @@ acpi_status acpi_reset(void)
 
 	if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
 		/*
-		 * For I/O space, write directly to the OSL. This bypasses the port
-		 * validation mechanism, which may block a valid write to the reset
-		 * register.
+		 * For I/O space, write directly to the OSL. This
+		 * bypasses the port validation mechanism, which may
+		 * block a valid write to the reset register. Spec
+		 * section 4.7.3.6 requires register width to be 8.
 		 */
 		status =
 		    acpi_os_write_port((acpi_io_address) reset_reg->address,
-				       acpi_gbl_FADT.reset_value,
-				       reset_reg->bit_width);
+				       acpi_gbl_FADT.reset_value, 8);
 	} else {
 		/* Write the reset value to the reset register */
 
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#40 lore raw

PATCH 37/42 ACPI: Bug compatibility for Windows on the ACPI reboot vector

In reply to Len Brown

From: Matthew Garrett <[email protected]>

Windows ignores the bit_offset and bit_width, despite the spec requiring that they be validated. Drop the checks so that we match this behaviour. Windows also goes straight for the keyboard controller if the ACPI reboot fails, so we shouldn't sleep if we're still alive.

---
 drivers/acpi/reboot.c |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)
drivers/acpi/reboot.c +4 -5
index 93f9114..4870aaa 100644
@@ -15,9 +15,10 @@ void acpi_reboot(void)
 
 	rr = &acpi_gbl_FADT.reset_register;
 
-	/* Is the reset register supported? */
-	if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
-	    rr->bit_width != 8 || rr->bit_offset != 0)
+	/* Is the reset register supported? The spec says we should be
+	 * checking the bit width and bit offset, but Windows ignores
+	 * these fields */
+	if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
 		return;
 
 	reset_value = acpi_gbl_FADT.reset_value;
@@ -45,6 +46,4 @@ void acpi_reboot(void)
 		acpi_reset();
 		break;
 	}
-	/* Wait ten seconds */
-	acpi_os_stall(10000000);
 }
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#41 lore raw

PATCH 38/42 ACPI: Make sure the FADT is at least rev 2 before using the reset register

In reply to Len Brown

From: Matthew Garrett <[email protected]>

The reset register was only introduced with version 2 of the FADT, so we should check that the FADT revision before trusting its contents.

---
 drivers/acpi/reboot.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
drivers/acpi/reboot.c +5 -0
index 4870aaa..a6c77e8b 100644
@@ -15,6 +15,11 @@ void acpi_reboot(void)
 
 	rr = &acpi_gbl_FADT.reset_register;
 
+	/* ACPI reset register was only introduced with v2 of the FADT */
+
+	if (acpi_gbl_FADT.header.revision < 2)
+		return;
+
 	/* Is the reset register supported? The spec says we should be
 	 * checking the bit width and bit offset, but Windows ignores
 	 * these fields */
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#42 lore raw

PATCH 39/42 ACPICA: Header support for SLIC table

In reply to Len Brown

From: Bob Moore <[email protected]>

We finally have the definition for this table.

---
 include/acpi/actbl2.h |   64 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 63 insertions(+), 1 deletions(-)
include/acpi/actbl2.h +63 -1
index 0fc15df..58bdd05 100644
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Name: actbl2.h - ACPI Specification Revision 2.0 Tables
+ * Name: actbl2.h - ACPI Table Definitions (tables not in ACPI spec)
  *
  *****************************************************************************/
 
@@ -716,6 +716,68 @@ struct acpi_table_mchi {
 
 /*******************************************************************************
  *
+ * SLIC - Software Licensing Description Table
+ *        Version 1
+ *
+ * Conforms to "OEM Activation 2.0 for Windows Vista Operating Systems",
+ * Copyright 2006
+ *
+ ******************************************************************************/
+
+/* Basic SLIC table is only the common ACPI header */
+
+struct acpi_table_slic {
+	struct acpi_table_header header;	/* Common ACPI table header */
+};
+
+/* Common SLIC subtable header */
+
+struct acpi_slic_header {
+	u32 type;
+	u32 length;
+};
+
+/* Values for Type field above */
+
+enum acpi_slic_type {
+	ACPI_SLIC_TYPE_PUBLIC_KEY = 0,
+	ACPI_SLIC_TYPE_WINDOWS_MARKER = 1,
+	ACPI_SLIC_TYPE_RESERVED = 2	/* 2 and greater are reserved */
+};
+
+/*
+ * SLIC Sub-tables, correspond to Type in struct acpi_slic_header
+ */
+
+/* 0: Public Key Structure */
+
+struct acpi_slic_key {
+	struct acpi_slic_header header;
+	u8 key_type;
+	u8 version;
+	u16 reserved;
+	u32 algorithm;
+	char magic[4];
+	u32 bit_length;
+	u32 exponent;
+	u8 modulus[128];
+};
+
+/* 1: Windows Marker Structure */
+
+struct acpi_slic_marker {
+	struct acpi_slic_header header;
+	u32 version;
+	char oem_id[ACPI_OEM_ID_SIZE];	/* ASCII OEM identification */
+	char oem_table_id[ACPI_OEM_TABLE_ID_SIZE];	/* ASCII OEM table identification */
+	char windows_flag[8];
+	u32 slic_version;
+	u8 reserved[16];
+	u8 signature[128];
+};
+
+/*******************************************************************************
+ *
  * SPCR - Serial Port Console Redirection table
  *        Version 1
  *
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#43 lore raw

PATCH 40/42 ACPICA: Update version to 20110316

In reply to Len Brown

From: Bob Moore <[email protected]>

Version 20110316.

---
 include/acpi/acpixf.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/acpi/acpixf.h +1 -1
index ec90854..f6ad63d 100644
@@ -47,7 +47,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20110211
+#define ACPI_CA_VERSION                 0x20110316
 
 #include "actypes.h"
 #include "actbl.h"
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#44 lore raw

PATCH 41/42 ACPI: make acpi_pad /sys output more readable

In reply to Len Brown

From: Naga Chumbalkar <[email protected]>

Make /sys output from acpi_pad more readable.

Before the fix:

# cat idlecpus idlepct rrtime
00000000510

After the fix:

# cat idlecpus idlepct rrtime
00000000
5
10
---
 drivers/acpi/acpi_pad.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)
drivers/acpi/acpi_pad.c +7 -4
index 6afceb3..474be3a 100644
@@ -298,7 +298,7 @@ static ssize_t acpi_pad_rrtime_store(struct device *dev,
 static ssize_t acpi_pad_rrtime_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d", round_robin_time);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", round_robin_time);
 }
 static DEVICE_ATTR(rrtime, S_IRUGO|S_IWUSR,
 	acpi_pad_rrtime_show,
@@ -321,7 +321,7 @@ static ssize_t acpi_pad_idlepct_store(struct device *dev,
 static ssize_t acpi_pad_idlepct_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d", idle_pct);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", idle_pct);
 }
 static DEVICE_ATTR(idlepct, S_IRUGO|S_IWUSR,
 	acpi_pad_idlepct_show,
@@ -342,8 +342,11 @@ static ssize_t acpi_pad_idlecpus_store(struct device *dev,
 static ssize_t acpi_pad_idlecpus_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return cpumask_scnprintf(buf, PAGE_SIZE,
-		to_cpumask(pad_busy_cpus_bits));
+	int n = 0;
+	n = cpumask_scnprintf(buf, PAGE_SIZE-2, to_cpumask(pad_busy_cpus_bits));
+	buf[n++] = '\n';
+	buf[n] = '\0';
+	return n;
 }
 static DEVICE_ATTR(idlecpus, S_IRUGO|S_IWUSR,
 	acpi_pad_idlecpus_show,
Signature · 1 line
1.7.4.1.343.ga91df
author reviewer
#45 lore raw

PATCH 42/42 ACPI: minor printk format change in acpi_pad

In reply to Len Brown

From: Naga Chumbalkar <[email protected]>

Minor format change.

---
 drivers/acpi/acpi_pad.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/acpi/acpi_pad.c +1 -1
index 474be3a..a43fa1a 100644
@@ -456,7 +456,7 @@ static void acpi_pad_notify(acpi_handle handle, u32 event,
 			dev_name(&device->dev), event, 0);
 		break;
 	default:
-		printk(KERN_WARNING"Unsupported event [0x%x]\n", event);
+		printk(KERN_WARNING "Unsupported event [0x%x]\n", event);
 		break;
 	}
 }
Signature · 1 line
1.7.4.1.343.ga91df