Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branches 'acpi-pnp', 'acpi-soc', 'pm-domains' and 'pm-sleep'

* acpi-pnp:
ACPI / PNP: Reserve ACPI resources at the fs_initcall_sync stage

* acpi-soc:
ACPI / LPSS: Fix up acpi_lpss_create_device()

* pm-domains:
PM / Domains: Avoid infinite loops in attach/detach code

* pm-sleep:
PM / hibernate: clarify resume documentation

+45 -207
+11 -2
Documentation/power/swsusp.txt
··· 410 410 411 411 Q: Can I suspend-to-disk using a swap partition under LVM? 412 412 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/ 415 424 416 425 Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were 417 426 compiled with the similar configuration files. Anyway I found that
+5 -2
drivers/acpi/acpi_lpss.c
··· 352 352 pdata->mmio_size = resource_size(rentry->res); 353 353 pdata->mmio_base = ioremap(rentry->res->start, 354 354 pdata->mmio_size); 355 - if (!pdata->mmio_base) 356 - goto err_out; 357 355 break; 358 356 } 359 357 360 358 acpi_dev_free_resource_list(&resource_list); 359 + 360 + if (!pdata->mmio_base) { 361 + ret = -ENOMEM; 362 + goto err_out; 363 + } 361 364 362 365 pdata->dev_desc = dev_desc; 363 366
+9 -3
drivers/acpi/osl.c
··· 175 175 if (!addr || !length) 176 176 return; 177 177 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); 179 183 } 180 184 181 - static void __init acpi_reserve_resources(void) 185 + static int __init acpi_reserve_resources(void) 182 186 { 183 187 acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, 184 188 "ACPI PM1a_EVT_BLK"); ··· 211 207 if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) 212 208 acpi_request_region(&acpi_gbl_FADT.xgpe1_block, 213 209 acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); 210 + 211 + return 0; 214 212 } 213 + fs_initcall_sync(acpi_reserve_resources); 215 214 216 215 void acpi_os_printf(const char *fmt, ...) 217 216 { ··· 1869 1862 1870 1863 acpi_status __init acpi_os_initialize1(void) 1871 1864 { 1872 - acpi_reserve_resources(); 1873 1865 kacpid_wq = alloc_workqueue("kacpid", 0, 1); 1874 1866 kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); 1875 1867 kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);
-162
drivers/acpi/resource.c
··· 26 26 #include <linux/device.h> 27 27 #include <linux/export.h> 28 28 #include <linux/ioport.h> 29 - #include <linux/list.h> 30 29 #include <linux/slab.h> 31 30 32 31 #ifdef CONFIG_X86 ··· 621 622 return (type & types) ? 0 : 1; 622 623 } 623 624 EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); 624 - 625 - struct reserved_region { 626 - struct list_head node; 627 - u64 start; 628 - u64 end; 629 - }; 630 - 631 - static LIST_HEAD(reserved_io_regions); 632 - static LIST_HEAD(reserved_mem_regions); 633 - 634 - static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags, 635 - char *desc) 636 - { 637 - unsigned int length = end - start + 1; 638 - struct resource *res; 639 - 640 - res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ? 641 - request_region(start, length, desc) : 642 - request_mem_region(start, length, desc); 643 - if (!res) 644 - return -EIO; 645 - 646 - res->flags &= ~flags; 647 - return 0; 648 - } 649 - 650 - static int add_region_before(u64 start, u64 end, u8 space_id, 651 - unsigned long flags, char *desc, 652 - struct list_head *head) 653 - { 654 - struct reserved_region *reg; 655 - int error; 656 - 657 - reg = kmalloc(sizeof(*reg), GFP_KERNEL); 658 - if (!reg) 659 - return -ENOMEM; 660 - 661 - error = request_range(start, end, space_id, flags, desc); 662 - if (error) { 663 - kfree(reg); 664 - return error; 665 - } 666 - 667 - reg->start = start; 668 - reg->end = end; 669 - list_add_tail(&reg->node, head); 670 - return 0; 671 - } 672 - 673 - /** 674 - * acpi_reserve_region - Reserve an I/O or memory region as a system resource. 675 - * @start: Starting address of the region. 676 - * @length: Length of the region. 677 - * @space_id: Identifier of address space to reserve the region from. 678 - * @flags: Resource flags to clear for the region after requesting it. 679 - * @desc: Region description (for messages). 680 - * 681 - * Reserve an I/O or memory region as a system resource to prevent others from 682 - * using it. If the new region overlaps with one of the regions (in the given 683 - * address space) already reserved by this routine, only the non-overlapping 684 - * parts of it will be reserved. 685 - * 686 - * Returned is either 0 (success) or a negative error code indicating a resource 687 - * reservation problem. It is the code of the first encountered error, but the 688 - * routine doesn't abort until it has attempted to request all of the parts of 689 - * the new region that don't overlap with other regions reserved previously. 690 - * 691 - * The resources requested by this routine are never released. 692 - */ 693 - int acpi_reserve_region(u64 start, unsigned int length, u8 space_id, 694 - unsigned long flags, char *desc) 695 - { 696 - struct list_head *regions; 697 - struct reserved_region *reg; 698 - u64 end = start + length - 1; 699 - int ret = 0, error = 0; 700 - 701 - if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) 702 - regions = &reserved_io_regions; 703 - else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) 704 - regions = &reserved_mem_regions; 705 - else 706 - return -EINVAL; 707 - 708 - if (list_empty(regions)) 709 - return add_region_before(start, end, space_id, flags, desc, regions); 710 - 711 - list_for_each_entry(reg, regions, node) 712 - if (reg->start == end + 1) { 713 - /* The new region can be prepended to this one. */ 714 - ret = request_range(start, end, space_id, flags, desc); 715 - if (!ret) 716 - reg->start = start; 717 - 718 - return ret; 719 - } else if (reg->start > end) { 720 - /* No overlap. Add the new region here and get out. */ 721 - return add_region_before(start, end, space_id, flags, 722 - desc, &reg->node); 723 - } else if (reg->end == start - 1) { 724 - goto combine; 725 - } else if (reg->end >= start) { 726 - goto overlap; 727 - } 728 - 729 - /* The new region goes after the last existing one. */ 730 - return add_region_before(start, end, space_id, flags, desc, regions); 731 - 732 - overlap: 733 - /* 734 - * The new region overlaps an existing one. 735 - * 736 - * The head part of the new region immediately preceding the existing 737 - * overlapping one can be combined with it right away. 738 - */ 739 - if (reg->start > start) { 740 - error = request_range(start, reg->start - 1, space_id, flags, desc); 741 - if (error) 742 - ret = error; 743 - else 744 - reg->start = start; 745 - } 746 - 747 - combine: 748 - /* 749 - * The new region is adjacent to an existing one. If it extends beyond 750 - * that region all the way to the next one, it is possible to combine 751 - * all three of them. 752 - */ 753 - while (reg->end < end) { 754 - struct reserved_region *next = NULL; 755 - u64 a = reg->end + 1, b = end; 756 - 757 - if (!list_is_last(&reg->node, regions)) { 758 - next = list_next_entry(reg, node); 759 - if (next->start <= end) 760 - b = next->start - 1; 761 - } 762 - error = request_range(a, b, space_id, flags, desc); 763 - if (!error) { 764 - if (next && next->start == b + 1) { 765 - reg->end = next->end; 766 - list_del(&next->node); 767 - kfree(next); 768 - } else { 769 - reg->end = end; 770 - break; 771 - } 772 - } else if (next) { 773 - if (!ret) 774 - ret = error; 775 - 776 - reg = next; 777 - } else { 778 - break; 779 - } 780 - } 781 - 782 - return ret ? ret : error; 783 - } 784 - EXPORT_SYMBOL_GPL(acpi_reserve_region);
+11 -2
drivers/base/power/domain.c
··· 6 6 * This file is released under the GPLv2. 7 7 */ 8 8 9 + #include <linux/delay.h> 9 10 #include <linux/kernel.h> 10 11 #include <linux/io.h> 11 12 #include <linux/platform_device.h> ··· 19 18 #include <linux/sched.h> 20 19 #include <linux/suspend.h> 21 20 #include <linux/export.h> 21 + 22 + #define GENPD_RETRY_MAX_MS 250 /* Approximate */ 22 23 23 24 #define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \ 24 25 ({ \ ··· 2134 2131 static void genpd_dev_pm_detach(struct device *dev, bool power_off) 2135 2132 { 2136 2133 struct generic_pm_domain *pd; 2134 + unsigned int i; 2137 2135 int ret = 0; 2138 2136 2139 2137 pd = pm_genpd_lookup_dev(dev); ··· 2143 2139 2144 2140 dev_dbg(dev, "removing from PM domain %s\n", pd->name); 2145 2141 2146 - while (1) { 2142 + for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { 2147 2143 ret = pm_genpd_remove_device(pd, dev); 2148 2144 if (ret != -EAGAIN) 2149 2145 break; 2146 + 2147 + mdelay(i); 2150 2148 cond_resched(); 2151 2149 } 2152 2150 ··· 2189 2183 { 2190 2184 struct of_phandle_args pd_args; 2191 2185 struct generic_pm_domain *pd; 2186 + unsigned int i; 2192 2187 int ret; 2193 2188 2194 2189 if (!dev->of_node) ··· 2225 2218 2226 2219 dev_dbg(dev, "adding to PM domain %s\n", pd->name); 2227 2220 2228 - while (1) { 2221 + for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { 2229 2222 ret = pm_genpd_add_device(pd, dev); 2230 2223 if (ret != -EAGAIN) 2231 2224 break; 2225 + 2226 + mdelay(i); 2232 2227 cond_resched(); 2233 2228 } 2234 2229
+9 -26
drivers/pnp/system.c
··· 7 7 * Bjorn Helgaas <bjorn.helgaas@hp.com> 8 8 */ 9 9 10 - #include <linux/acpi.h> 11 10 #include <linux/pnp.h> 12 11 #include <linux/device.h> 13 12 #include <linux/init.h> ··· 22 23 {"", 0} 23 24 }; 24 25 25 - #ifdef CONFIG_ACPI 26 - static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc) 27 - { 28 - u8 space_id = io ? ACPI_ADR_SPACE_SYSTEM_IO : ACPI_ADR_SPACE_SYSTEM_MEMORY; 29 - return !acpi_reserve_region(start, length, space_id, IORESOURCE_BUSY, desc); 30 - } 31 - #else 32 - static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc) 33 - { 34 - struct resource *res; 35 - 36 - res = io ? request_region(start, length, desc) : 37 - request_mem_region(start, length, desc); 38 - if (res) { 39 - res->flags &= ~IORESOURCE_BUSY; 40 - return true; 41 - } 42 - return false; 43 - } 44 - #endif 45 - 46 26 static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) 47 27 { 48 28 char *regionid; 49 29 const char *pnpid = dev_name(&dev->dev); 50 30 resource_size_t start = r->start, end = r->end; 51 - bool reserved; 31 + struct resource *res; 52 32 53 33 regionid = kmalloc(16, GFP_KERNEL); 54 34 if (!regionid) 55 35 return; 56 36 57 37 snprintf(regionid, 16, "pnp %s", pnpid); 58 - reserved = __reserve_range(start, end - start + 1, !!port, regionid); 59 - if (!reserved) 38 + if (port) 39 + res = request_region(start, end - start + 1, regionid); 40 + else 41 + res = request_mem_region(start, end - start + 1, regionid); 42 + if (res) 43 + res->flags &= ~IORESOURCE_BUSY; 44 + else 60 45 kfree(regionid); 61 46 62 47 /* ··· 49 66 * have double reservations. 50 67 */ 51 68 dev_info(&dev->dev, "%pR %s reserved\n", r, 52 - reserved ? "has been" : "could not be"); 69 + res ? "has been" : "could not be"); 53 70 } 54 71 55 72 static void reserve_resources_of_dev(struct pnp_dev *dev)
-10
include/linux/acpi.h
··· 309 309 310 310 int acpi_resources_are_enforced(void); 311 311 312 - int acpi_reserve_region(u64 start, unsigned int length, u8 space_id, 313 - unsigned long flags, char *desc); 314 - 315 312 #ifdef CONFIG_HIBERNATION 316 313 void __init acpi_no_s4_hw_signature(void); 317 314 #endif ··· 502 505 const char *name) 503 506 { 504 507 return 0; 505 - } 506 - 507 - static inline int acpi_reserve_region(u64 start, unsigned int length, 508 - u8 space_id, unsigned long flags, 509 - char *desc) 510 - { 511 - return -ENXIO; 512 508 } 513 509 514 510 struct acpi_table_header;