Merge branches 'pm-cpuidle', 'pm-cpufreq' and 'acpi-resources'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 16 Jul 2015 21:47:19 +0000 (23:47 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 16 Jul 2015 21:47:19 +0000 (23:47 +0200)
* pm-cpuidle:
  suspend-to-idle: Prevent RCU from complaining about tick_freeze()

* pm-cpufreq:
  cpufreq: Allow freq_table to be obtained for offline CPUs
  cpufreq: Initialize the governor again while restoring policy

* acpi-resources:
  ACPI / PCI: Fix regressions caused by resource_size_t overflow with 32-bit kernel

1  2  3  4 
drivers/acpi/resource.c

diff --combined drivers/acpi/resource.c
index 8244f013f21095a9508e80ef01621e0ffbaab106,10561ce16ed135165cdbc8e558cb2aaea263d13b,10561ce16ed135165cdbc8e558cb2aaea263d13b,e8d281739cbc32582259ec8a34e2e5edcd38b29c..f1c966e05078426455227d8f582a7ddd0f211cb2
    #include <linux/device.h>
    #include <linux/export.h>
    #include <linux/ioport.h>
 ---#include <linux/list.h>
    #include <linux/slab.h>
    
    #ifdef CONFIG_X86
@@@@@ -193,6 -194,6 -194,6 -194,7 +193,7 @@@@@ static bool acpi_decode_space(struct re
        u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
        bool wp = addr->info.mem.write_protect;
        u64 len = attr->address_length;
+++     u64 start, end, offset = 0;
        struct resource *res = &win->res;
    
        /*
                pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n",
                         addr->min_address_fixed, addr->max_address_fixed, len);
    
---     res->start = attr->minimum;
---     res->end = attr->maximum;
--- 
        /*
         * For bridges that translate addresses across the bridge,
         * translation_offset is the offset that must be added to the
         * primary side. Non-bridge devices must list 0 for all Address
         * Translation offset bits.
         */
---     if (addr->producer_consumer == ACPI_PRODUCER) {
---             res->start += attr->translation_offset;
---             res->end += attr->translation_offset;
---     } else if (attr->translation_offset) {
+++     if (addr->producer_consumer == ACPI_PRODUCER)
+++             offset = attr->translation_offset;
+++     else if (attr->translation_offset)
                pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
                         attr->translation_offset);
+++     start = attr->minimum + offset;
+++     end = attr->maximum + offset;
+++ 
+++     win->offset = offset;
+++     res->start = start;
+++     res->end = end;
+++     if (sizeof(resource_size_t) < sizeof(u64) &&
+++         (offset != win->offset || start != res->start || end != res->end)) {
+++             pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",
+++                     attr->minimum, attr->maximum);
+++             return false;
        }
    
        switch (addr->resource_type) {
                return false;
        }
    
---     win->offset = attr->translation_offset;
--- 
        if (addr->producer_consumer == ACPI_PRODUCER)
                res->flags |= IORESOURCE_WINDOW;
    
@@@@@ -621,3 -622,164 -622,164 -628,164 +627,3 @@@@@ int acpi_dev_filter_resource_type(struc
        return (type & types) ? 0 : 1;
    }
    EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
 ---
 ---struct reserved_region {
 ---    struct list_head node;
 ---    u64 start;
 ---    u64 end;
 ---};
 ---
 ---static LIST_HEAD(reserved_io_regions);
 ---static LIST_HEAD(reserved_mem_regions);
 ---
 ---static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags,
 ---                     char *desc)
 ---{
 ---    unsigned int length = end - start + 1;
 ---    struct resource *res;
 ---
 ---    res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ?
 ---            request_region(start, length, desc) :
 ---            request_mem_region(start, length, desc);
 ---    if (!res)
 ---            return -EIO;
 ---
 ---    res->flags &= ~flags;
 ---    return 0;
 ---}
 ---
 ---static int add_region_before(u64 start, u64 end, u8 space_id,
 ---                         unsigned long flags, char *desc,
 ---                         struct list_head *head)
 ---{
 ---    struct reserved_region *reg;
 ---    int error;
 ---
 ---    reg = kmalloc(sizeof(*reg), GFP_KERNEL);
 ---    if (!reg)
 ---            return -ENOMEM;
 ---
 ---    error = request_range(start, end, space_id, flags, desc);
 ---    if (error) {
 ---            kfree(reg);
 ---            return error;
 ---    }
 ---
 ---    reg->start = start;
 ---    reg->end = end;
 ---    list_add_tail(&reg->node, head);
 ---    return 0;
 ---}
 ---
 ---/**
 --- * acpi_reserve_region - Reserve an I/O or memory region as a system resource.
 --- * @start: Starting address of the region.
 --- * @length: Length of the region.
 --- * @space_id: Identifier of address space to reserve the region from.
 --- * @flags: Resource flags to clear for the region after requesting it.
 --- * @desc: Region description (for messages).
 --- *
 --- * Reserve an I/O or memory region as a system resource to prevent others from
 --- * using it.  If the new region overlaps with one of the regions (in the given
 --- * address space) already reserved by this routine, only the non-overlapping
 --- * parts of it will be reserved.
 --- *
 --- * Returned is either 0 (success) or a negative error code indicating a resource
 --- * reservation problem.  It is the code of the first encountered error, but the
 --- * routine doesn't abort until it has attempted to request all of the parts of
 --- * the new region that don't overlap with other regions reserved previously.
 --- *
 --- * The resources requested by this routine are never released.
 --- */
 ---int acpi_reserve_region(u64 start, unsigned int length, u8 space_id,
 ---                    unsigned long flags, char *desc)
 ---{
 ---    struct list_head *regions;
 ---    struct reserved_region *reg;
 ---    u64 end = start + length - 1;
 ---    int ret = 0, error = 0;
 ---
 ---    if (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
 ---            regions = &reserved_io_regions;
 ---    else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
 ---            regions = &reserved_mem_regions;
 ---    else
 ---            return -EINVAL;
 ---
 ---    if (list_empty(regions))
 ---            return add_region_before(start, end, space_id, flags, desc, regions);
 ---
 ---    list_for_each_entry(reg, regions, node)
 ---            if (reg->start == end + 1) {
 ---                    /* The new region can be prepended to this one. */
 ---                    ret = request_range(start, end, space_id, flags, desc);
 ---                    if (!ret)
 ---                            reg->start = start;
 ---
 ---                    return ret;
 ---            } else if (reg->start > end) {
 ---                    /* No overlap.  Add the new region here and get out. */
 ---                    return add_region_before(start, end, space_id, flags,
 ---                                             desc, &reg->node);
 ---            } else if (reg->end == start - 1) {
 ---                    goto combine;
 ---            } else if (reg->end >= start) {
 ---                    goto overlap;
 ---            }
 ---
 ---    /* The new region goes after the last existing one. */
 ---    return add_region_before(start, end, space_id, flags, desc, regions);
 ---
 --- overlap:
 ---    /*
 ---     * The new region overlaps an existing one.
 ---     *
 ---     * The head part of the new region immediately preceding the existing
 ---     * overlapping one can be combined with it right away.
 ---     */
 ---    if (reg->start > start) {
 ---            error = request_range(start, reg->start - 1, space_id, flags, desc);
 ---            if (error)
 ---                    ret = error;
 ---            else
 ---                    reg->start = start;
 ---    }
 ---
 --- combine:
 ---    /*
 ---     * The new region is adjacent to an existing one.  If it extends beyond
 ---     * that region all the way to the next one, it is possible to combine
 ---     * all three of them.
 ---     */
 ---    while (reg->end < end) {
 ---            struct reserved_region *next = NULL;
 ---            u64 a = reg->end + 1, b = end;
 ---
 ---            if (!list_is_last(&reg->node, regions)) {
 ---                    next = list_next_entry(reg, node);
 ---                    if (next->start <= end)
 ---                            b = next->start - 1;
 ---            }
 ---            error = request_range(a, b, space_id, flags, desc);
 ---            if (!error) {
 ---                    if (next && next->start == b + 1) {
 ---                            reg->end = next->end;
 ---                            list_del(&next->node);
 ---                            kfree(next);
 ---                    } else {
 ---                            reg->end = end;
 ---                            break;
 ---                    }
 ---            } else if (next) {
 ---                    if (!ret)
 ---                            ret = error;
 ---
 ---                    reg = next;
 ---            } else {
 ---                    break;
 ---            }
 ---    }
 ---
 ---    return ret ? ret : error;
 ---}
 ---EXPORT_SYMBOL_GPL(acpi_reserve_region);