Skip to content

Commit 883a2df

Browse files
committed
Merge tag 'pm+acpi-4.2-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management and ACPI updates from Rafael Wysocki: "These are fixes on top of the previous PM+ACPI pull requests (including one fix for a 4.1 regression) and two commits adding _CLS-based device enumeration support to the ACPI core and the ATA subsystem that waited for the latest ACPICA changes to be merged. Specifics: - Fix for an ACPI resources management regression introduced during the 4.1 cycle (that unfortunately went into -stable) effectively reverting the bad commit along with the recent fixups on top of it and using an alternative approach to address the underlying issue (Rafael J Wysocki). - Fix for a memory leak and an incorrect return value in an error code path in the ACPI LPSS (Low-Power Subsystem) driver (Rafael J Wysocki). - Fix for a leftover dangling pointer in an error code path in the new wakeup IRQ support code (Rafael J Wysocki). - Fix to prevent infinite loops (due to errors in other places) from happening in the core generic PM domains support code (Geert Uytterhoeven). - Hibernation documentation update/clarification (Uwe Geuder). - Support for _CLS-based device enumeration in the ACPI core and in the ATA subsystem (Suravee Suthikulpanit)" * tag 'pm+acpi-4.2-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PM / wakeirq: Avoid setting power.wakeirq too hastily ata: ahci_platform: Add ACPI _CLS matching ACPI / scan: Add support for ACPI _CLS device matching PM / hibernate: clarify resume documentation PM / Domains: Avoid infinite loops in attach/detach code ACPI / LPSS: Fix up acpi_lpss_create_device() ACPI / PNP: Reserve ACPI resources at the fs_initcall_sync stage
2 parents 331c584 + 8076ca4 commit 883a2df

File tree

15 files changed

+148
-240
lines changed

15 files changed

+148
-240
lines changed

Documentation/power/swsusp.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,17 @@ Documentation/usb/persist.txt.
410410

411411
Q: Can I suspend-to-disk using a swap partition under LVM?
412412

413-
A: No. You can suspend successfully, but you'll not be able to
414-
resume. uswsusp should be able to work with LVM. See suspend.sf.net.
413+
A: Yes and No. You can suspend successfully, but the kernel will not be able
414+
to resume on its own. You need an initramfs that can recognize the resume
415+
situation, activate the logical volume containing the swap volume (but not
416+
touch any filesystems!), and eventually call
417+
418+
echo -n "$major:$minor" > /sys/power/resume
419+
420+
where $major and $minor are the respective major and minor device numbers of
421+
the swap volume.
422+
423+
uswsusp works with LVM, too. See http://suspend.sourceforge.net/
415424

416425
Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were
417426
compiled with the similar configuration files. Anyway I found that

drivers/acpi/acpi_lpss.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,13 +352,16 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
352352
pdata->mmio_size = resource_size(rentry->res);
353353
pdata->mmio_base = ioremap(rentry->res->start,
354354
pdata->mmio_size);
355-
if (!pdata->mmio_base)
356-
goto err_out;
357355
break;
358356
}
359357

360358
acpi_dev_free_resource_list(&resource_list);
361359

360+
if (!pdata->mmio_base) {
361+
ret = -ENOMEM;
362+
goto err_out;
363+
}
364+
362365
pdata->dev_desc = dev_desc;
363366

364367
if (dev_desc->setup)

drivers/acpi/osl.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,14 @@ static void __init acpi_request_region (struct acpi_generic_address *gas,
175175
if (!addr || !length)
176176
return;
177177

178-
acpi_reserve_region(addr, length, gas->space_id, 0, desc);
178+
/* Resources are never freed */
179+
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
180+
request_region(addr, length, desc);
181+
else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
182+
request_mem_region(addr, length, desc);
179183
}
180184

181-
static void __init acpi_reserve_resources(void)
185+
static int __init acpi_reserve_resources(void)
182186
{
183187
acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length,
184188
"ACPI PM1a_EVT_BLK");
@@ -207,7 +211,10 @@ static void __init acpi_reserve_resources(void)
207211
if (!(acpi_gbl_FADT.gpe1_block_length & 0x1))
208212
acpi_request_region(&acpi_gbl_FADT.xgpe1_block,
209213
acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK");
214+
215+
return 0;
210216
}
217+
fs_initcall_sync(acpi_reserve_resources);
211218

212219
void acpi_os_printf(const char *fmt, ...)
213220
{
@@ -1862,7 +1869,6 @@ acpi_status __init acpi_os_initialize(void)
18621869

18631870
acpi_status __init acpi_os_initialize1(void)
18641871
{
1865-
acpi_reserve_resources();
18661872
kacpid_wq = alloc_workqueue("kacpid", 0, 1);
18671873
kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
18681874
kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);

drivers/acpi/resource.c

Lines changed: 0 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <linux/device.h>
2727
#include <linux/export.h>
2828
#include <linux/ioport.h>
29-
#include <linux/list.h>
3029
#include <linux/slab.h>
3130

3231
#ifdef CONFIG_X86
@@ -622,164 +621,3 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares,
622621
return (type & types) ? 0 : 1;
623622
}
624623
EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
625-
626-
struct reserved_region {
627-
struct list_head node;
628-
u64 start;
629-
u64 end;
630-
};
631-
632-
static LIST_HEAD(reserved_io_regions);
633-
static LIST_HEAD(reserved_mem_regions);
634-
635-
static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags,
636-
char *desc)
637-
{
638-
unsigned int length = end - start + 1;
639-
struct resource *res;
640-
641-
res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ?
642-
request_region(start, length, desc) :
643-
request_mem_region(start, length, desc);
644-
if (!res)
645-
return -EIO;
646-
647-
res->flags &= ~flags;
648-
return 0;
649-
}
650-
651-
static int add_region_before(u64 start, u64 end, u8 space_id,
652-
unsigned long flags, char *desc,
653-
struct list_head *head)
654-
{
655-
struct reserved_region *reg;
656-
int error;
657-
658-
reg = kmalloc(sizeof(*reg), GFP_KERNEL);
659-
if (!reg)
660-
return -ENOMEM;
661-
662-
error = request_range(start, end, space_id, flags, desc);
663-
if (error) {
664-
kfree(reg);
665-
return error;
666-
}
667-
668-
reg->start = start;
669-
reg->end = end;
670-
list_add_tail(&reg->node, head);
671-
return 0;
672-
}
673-
674-
/**
675-
* acpi_reserve_region - Reserve an I/O or memory region as a system resource.
676-
* @start: Starting address of the region.
677-
* @length: Length of the region.
678-
* @space_id: Identifier of address space to reserve the region from.
679-
* @flags: Resource flags to clear for the region after requesting it.
680-
* @desc: Region description (for messages).
681-
*
682-
* Reserve an I/O or memory region as a system resource to prevent others from
683-
* using it. If the new region overlaps with one of the regions (in the given
684-
* address space) already reserved by this routine, only the non-overlapping
685-
* parts of it will be reserved.
686-
*
687-
* Returned is either 0 (success) or a negative error code indicating a resource
688-
* reservation problem. It is the code of the first encountered error, but the
689-
* routine doesn't abort until it has attempted to request all of the parts of
690-
* the new region that don't overlap with other regions reserved previously.
691-
*
692-
* The resources requested by this routine are never released.
693-
*/
694-
int acpi_reserve_region(u64 start, unsigned int length, u8 space_id,
695-
unsigned long flags, char *desc)
696-
{
697-
struct list_head *regions;
698-
struct reserved_region *reg;
699-
u64 end = start + length - 1;
700-
int ret = 0, error = 0;
701-
702-
if (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
703-
regions = &reserved_io_regions;
704-
else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
705-
regions = &reserved_mem_regions;
706-
else
707-
return -EINVAL;
708-
709-
if (list_empty(regions))
710-
return add_region_before(start, end, space_id, flags, desc, regions);
711-
712-
list_for_each_entry(reg, regions, node)
713-
if (reg->start == end + 1) {
714-
/* The new region can be prepended to this one. */
715-
ret = request_range(start, end, space_id, flags, desc);
716-
if (!ret)
717-
reg->start = start;
718-
719-
return ret;
720-
} else if (reg->start > end) {
721-
/* No overlap. Add the new region here and get out. */
722-
return add_region_before(start, end, space_id, flags,
723-
desc, &reg->node);
724-
} else if (reg->end == start - 1) {
725-
goto combine;
726-
} else if (reg->end >= start) {
727-
goto overlap;
728-
}
729-
730-
/* The new region goes after the last existing one. */
731-
return add_region_before(start, end, space_id, flags, desc, regions);
732-
733-
overlap:
734-
/*
735-
* The new region overlaps an existing one.
736-
*
737-
* The head part of the new region immediately preceding the existing
738-
* overlapping one can be combined with it right away.
739-
*/
740-
if (reg->start > start) {
741-
error = request_range(start, reg->start - 1, space_id, flags, desc);
742-
if (error)
743-
ret = error;
744-
else
745-
reg->start = start;
746-
}
747-
748-
combine:
749-
/*
750-
* The new region is adjacent to an existing one. If it extends beyond
751-
* that region all the way to the next one, it is possible to combine
752-
* all three of them.
753-
*/
754-
while (reg->end < end) {
755-
struct reserved_region *next = NULL;
756-
u64 a = reg->end + 1, b = end;
757-
758-
if (!list_is_last(&reg->node, regions)) {
759-
next = list_next_entry(reg, node);
760-
if (next->start <= end)
761-
b = next->start - 1;
762-
}
763-
error = request_range(a, b, space_id, flags, desc);
764-
if (!error) {
765-
if (next && next->start == b + 1) {
766-
reg->end = next->end;
767-
list_del(&next->node);
768-
kfree(next);
769-
} else {
770-
reg->end = end;
771-
break;
772-
}
773-
} else if (next) {
774-
if (!ret)
775-
ret = error;
776-
777-
reg = next;
778-
} else {
779-
break;
780-
}
781-
}
782-
783-
return ret ? ret : error;
784-
}
785-
EXPORT_SYMBOL_GPL(acpi_reserve_region);

drivers/acpi/scan.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,29 @@ static bool acpi_of_match_device(struct acpi_device *adev,
10191019
return false;
10201020
}
10211021

1022+
static bool __acpi_match_device_cls(const struct acpi_device_id *id,
1023+
struct acpi_hardware_id *hwid)
1024+
{
1025+
int i, msk, byte_shift;
1026+
char buf[3];
1027+
1028+
if (!id->cls)
1029+
return false;
1030+
1031+
/* Apply class-code bitmask, before checking each class-code byte */
1032+
for (i = 1; i <= 3; i++) {
1033+
byte_shift = 8 * (3 - i);
1034+
msk = (id->cls_msk >> byte_shift) & 0xFF;
1035+
if (!msk)
1036+
continue;
1037+
1038+
sprintf(buf, "%02x", (id->cls >> byte_shift) & msk);
1039+
if (strncmp(buf, &hwid->id[(i - 1) * 2], 2))
1040+
return false;
1041+
}
1042+
return true;
1043+
}
1044+
10221045
static const struct acpi_device_id *__acpi_match_device(
10231046
struct acpi_device *device,
10241047
const struct acpi_device_id *ids,
@@ -1036,9 +1059,12 @@ static const struct acpi_device_id *__acpi_match_device(
10361059

10371060
list_for_each_entry(hwid, &device->pnp.ids, list) {
10381061
/* First, check the ACPI/PNP IDs provided by the caller. */
1039-
for (id = ids; id->id[0]; id++)
1040-
if (!strcmp((char *) id->id, hwid->id))
1062+
for (id = ids; id->id[0] || id->cls; id++) {
1063+
if (id->id[0] && !strcmp((char *) id->id, hwid->id))
10411064
return id;
1065+
else if (id->cls && __acpi_match_device_cls(id, hwid))
1066+
return id;
1067+
}
10421068

10431069
/*
10441070
* Next, check ACPI_DT_NAMESPACE_HID and try to match the
@@ -2101,6 +2127,8 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
21012127
if (info->valid & ACPI_VALID_UID)
21022128
pnp->unique_id = kstrdup(info->unique_id.string,
21032129
GFP_KERNEL);
2130+
if (info->valid & ACPI_VALID_CLS)
2131+
acpi_add_id(pnp, info->class_code.string);
21042132

21052133
kfree(info);
21062134

drivers/ata/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ config ATA_VERBOSE_ERROR
4848

4949
config ATA_ACPI
5050
bool "ATA ACPI Support"
51-
depends on ACPI && PCI
51+
depends on ACPI
5252
default y
5353
help
5454
This option adds support for ATA-related ACPI objects.

drivers/ata/ahci_platform.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <linux/platform_device.h>
2121
#include <linux/libata.h>
2222
#include <linux/ahci_platform.h>
23+
#include <linux/acpi.h>
24+
#include <linux/pci_ids.h>
2325
#include "ahci.h"
2426

2527
#define DRV_NAME "ahci"
@@ -79,12 +81,19 @@ static const struct of_device_id ahci_of_match[] = {
7981
};
8082
MODULE_DEVICE_TABLE(of, ahci_of_match);
8183

84+
static const struct acpi_device_id ahci_acpi_match[] = {
85+
{ ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) },
86+
{},
87+
};
88+
MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
89+
8290
static struct platform_driver ahci_driver = {
8391
.probe = ahci_probe,
8492
.remove = ata_platform_remove_one,
8593
.driver = {
8694
.name = DRV_NAME,
8795
.of_match_table = ahci_of_match,
96+
.acpi_match_table = ahci_acpi_match,
8897
.pm = &ahci_pm_ops,
8998
},
9099
};

0 commit comments

Comments
 (0)