linux/drivers/acpi/resource.c
<<
>>
Prefs
   1/*
   2 * drivers/acpi/resource.c - ACPI device resources interpretation.
   3 *
   4 * Copyright (C) 2012, Intel Corp.
   5 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
   6 *
   7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   8 *
   9 *  This program is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License version 2 as published
  11 *  by the Free Software Foundation.
  12 *
  13 *  This program is distributed in the hope that it will be useful, but
  14 *  WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16 *  General Public License for more details.
  17 *
  18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  19 */
  20
  21#include <linux/acpi.h>
  22#include <linux/device.h>
  23#include <linux/export.h>
  24#include <linux/ioport.h>
  25#include <linux/slab.h>
  26#include <linux/irq.h>
  27
  28#ifdef CONFIG_X86
  29#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
  30static inline bool acpi_iospace_resource_valid(struct resource *res)
  31{
  32        /* On X86 IO space is limited to the [0 - 64K] IO port range */
  33        return res->end < 0x10003;
  34}
  35#else
  36#define valid_IRQ(i) (true)
  37/*
  38 * ACPI IO descriptors on arches other than X86 contain MMIO CPU physical
  39 * addresses mapping IO space in CPU physical address space, IO space
  40 * resources can be placed anywhere in the 64-bit physical address space.
  41 */
  42static inline bool
  43acpi_iospace_resource_valid(struct resource *res) { return true; }
  44#endif
  45
  46static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
  47{
  48        u64 reslen = end - start + 1;
  49
  50        /*
  51         * CHECKME: len might be required to check versus a minimum
  52         * length as well. 1 for io is fine, but for memory it does
  53         * not make any sense at all.
  54         * Note: some BIOSes report incorrect length for ACPI address space
  55         * descriptor, so remove check of 'reslen == len' to avoid regression.
  56         */
  57        if (len && reslen && start <= end)
  58                return true;
  59
  60        pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
  61                io ? "io" : "mem", start, end, len);
  62
  63        return false;
  64}
  65
  66static void acpi_dev_memresource_flags(struct resource *res, u64 len,
  67                                       u8 write_protect)
  68{
  69        res->flags = IORESOURCE_MEM;
  70
  71        if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))
  72                res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
  73
  74        if (write_protect == ACPI_READ_WRITE_MEMORY)
  75                res->flags |= IORESOURCE_MEM_WRITEABLE;
  76}
  77
  78static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
  79                                     u8 write_protect)
  80{
  81        res->start = start;
  82        res->end = start + len - 1;
  83        acpi_dev_memresource_flags(res, len, write_protect);
  84}
  85
  86/**
  87 * acpi_dev_resource_memory - Extract ACPI memory resource information.
  88 * @ares: Input ACPI resource object.
  89 * @res: Output generic resource object.
  90 *
  91 * Check if the given ACPI resource object represents a memory resource and
  92 * if that's the case, use the information in it to populate the generic
  93 * resource object pointed to by @res.
  94 *
  95 * Return:
  96 * 1) false with res->flags setting to zero: not the expected resource type
  97 * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
  98 * 3) true: valid assigned resource
  99 */
 100bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
 101{
 102        struct acpi_resource_memory24 *memory24;
 103        struct acpi_resource_memory32 *memory32;
 104        struct acpi_resource_fixed_memory32 *fixed_memory32;
 105
 106        switch (ares->type) {
 107        case ACPI_RESOURCE_TYPE_MEMORY24:
 108                memory24 = &ares->data.memory24;
 109                acpi_dev_get_memresource(res, memory24->minimum << 8,
 110                                         memory24->address_length << 8,
 111                                         memory24->write_protect);
 112                break;
 113        case ACPI_RESOURCE_TYPE_MEMORY32:
 114                memory32 = &ares->data.memory32;
 115                acpi_dev_get_memresource(res, memory32->minimum,
 116                                         memory32->address_length,
 117                                         memory32->write_protect);
 118                break;
 119        case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 120                fixed_memory32 = &ares->data.fixed_memory32;
 121                acpi_dev_get_memresource(res, fixed_memory32->address,
 122                                         fixed_memory32->address_length,
 123                                         fixed_memory32->write_protect);
 124                break;
 125        default:
 126                res->flags = 0;
 127                return false;
 128        }
 129
 130        return !(res->flags & IORESOURCE_DISABLED);
 131}
 132EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
 133
 134static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
 135                                      u8 io_decode, u8 translation_type)
 136{
 137        res->flags = IORESOURCE_IO;
 138
 139        if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))
 140                res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
 141
 142        if (!acpi_iospace_resource_valid(res))
 143                res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
 144
 145        if (io_decode == ACPI_DECODE_16)
 146                res->flags |= IORESOURCE_IO_16BIT_ADDR;
 147        if (translation_type == ACPI_SPARSE_TRANSLATION)
 148                res->flags |= IORESOURCE_IO_SPARSE;
 149}
 150
 151static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
 152                                    u8 io_decode)
 153{
 154        res->start = start;
 155        res->end = start + len - 1;
 156        acpi_dev_ioresource_flags(res, len, io_decode, 0);
 157}
 158
 159/**
 160 * acpi_dev_resource_io - Extract ACPI I/O resource information.
 161 * @ares: Input ACPI resource object.
 162 * @res: Output generic resource object.
 163 *
 164 * Check if the given ACPI resource object represents an I/O resource and
 165 * if that's the case, use the information in it to populate the generic
 166 * resource object pointed to by @res.
 167 *
 168 * Return:
 169 * 1) false with res->flags setting to zero: not the expected resource type
 170 * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
 171 * 3) true: valid assigned resource
 172 */
 173bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
 174{
 175        struct acpi_resource_io *io;
 176        struct acpi_resource_fixed_io *fixed_io;
 177
 178        switch (ares->type) {
 179        case ACPI_RESOURCE_TYPE_IO:
 180                io = &ares->data.io;
 181                acpi_dev_get_ioresource(res, io->minimum,
 182                                        io->address_length,
 183                                        io->io_decode);
 184                break;
 185        case ACPI_RESOURCE_TYPE_FIXED_IO:
 186                fixed_io = &ares->data.fixed_io;
 187                acpi_dev_get_ioresource(res, fixed_io->address,
 188                                        fixed_io->address_length,
 189                                        ACPI_DECODE_10);
 190                break;
 191        default:
 192                res->flags = 0;
 193                return false;
 194        }
 195
 196        return !(res->flags & IORESOURCE_DISABLED);
 197}
 198EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
 199
 200static bool acpi_decode_space(struct resource_win *win,
 201                              struct acpi_resource_address *addr,
 202                              struct acpi_address64_attribute *attr)
 203{
 204        u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
 205        bool wp = addr->info.mem.write_protect;
 206        u64 len = attr->address_length;
 207        u64 start, end, offset = 0;
 208        struct resource *res = &win->res;
 209
 210        /*
 211         * Filter out invalid descriptor according to ACPI Spec 5.0, section
 212         * 6.4.3.5 Address Space Resource Descriptors.
 213         */
 214        if ((addr->min_address_fixed != addr->max_address_fixed && len) ||
 215            (addr->min_address_fixed && addr->max_address_fixed && !len))
 216                pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n",
 217                         addr->min_address_fixed, addr->max_address_fixed, len);
 218
 219        /*
 220         * For bridges that translate addresses across the bridge,
 221         * translation_offset is the offset that must be added to the
 222         * address on the secondary side to obtain the address on the
 223         * primary side. Non-bridge devices must list 0 for all Address
 224         * Translation offset bits.
 225         */
 226        if (addr->producer_consumer == ACPI_PRODUCER)
 227                offset = attr->translation_offset;
 228        else if (attr->translation_offset)
 229                pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
 230                         attr->translation_offset);
 231        start = attr->minimum + offset;
 232        end = attr->maximum + offset;
 233
 234        win->offset = offset;
 235        res->start = start;
 236        res->end = end;
 237        if (sizeof(resource_size_t) < sizeof(u64) &&
 238            (offset != win->offset || start != res->start || end != res->end)) {
 239                pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",
 240                        attr->minimum, attr->maximum);
 241                return false;
 242        }
 243
 244        switch (addr->resource_type) {
 245        case ACPI_MEMORY_RANGE:
 246                acpi_dev_memresource_flags(res, len, wp);
 247                break;
 248        case ACPI_IO_RANGE:
 249                acpi_dev_ioresource_flags(res, len, iodec,
 250                                          addr->info.io.translation_type);
 251                break;
 252        case ACPI_BUS_NUMBER_RANGE:
 253                res->flags = IORESOURCE_BUS;
 254                break;
 255        default:
 256                return false;
 257        }
 258
 259        if (addr->producer_consumer == ACPI_PRODUCER)
 260                res->flags |= IORESOURCE_WINDOW;
 261
 262        if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
 263                res->flags |= IORESOURCE_PREFETCH;
 264
 265        return !(res->flags & IORESOURCE_DISABLED);
 266}
 267
 268/**
 269 * acpi_dev_resource_address_space - Extract ACPI address space information.
 270 * @ares: Input ACPI resource object.
 271 * @win: Output generic resource object.
 272 *
 273 * Check if the given ACPI resource object represents an address space resource
 274 * and if that's the case, use the information in it to populate the generic
 275 * resource object pointed to by @win.
 276 *
 277 * Return:
 278 * 1) false with win->res.flags setting to zero: not the expected resource type
 279 * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned
 280 *    resource
 281 * 3) true: valid assigned resource
 282 */
 283bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 284                                     struct resource_win *win)
 285{
 286        struct acpi_resource_address64 addr;
 287
 288        win->res.flags = 0;
 289        if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr)))
 290                return false;
 291
 292        return acpi_decode_space(win, (struct acpi_resource_address *)&addr,
 293                                 &addr.address);
 294}
 295EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
 296
 297/**
 298 * acpi_dev_resource_ext_address_space - Extract ACPI address space information.
 299 * @ares: Input ACPI resource object.
 300 * @win: Output generic resource object.
 301 *
 302 * Check if the given ACPI resource object represents an extended address space
 303 * resource and if that's the case, use the information in it to populate the
 304 * generic resource object pointed to by @win.
 305 *
 306 * Return:
 307 * 1) false with win->res.flags setting to zero: not the expected resource type
 308 * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned
 309 *    resource
 310 * 3) true: valid assigned resource
 311 */
 312bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
 313                                         struct resource_win *win)
 314{
 315        struct acpi_resource_extended_address64 *ext_addr;
 316
 317        win->res.flags = 0;
 318        if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
 319                return false;
 320
 321        ext_addr = &ares->data.ext_address64;
 322
 323        return acpi_decode_space(win, (struct acpi_resource_address *)ext_addr,
 324                                 &ext_addr->address);
 325}
 326EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
 327
 328/**
 329 * acpi_dev_irq_flags - Determine IRQ resource flags.
 330 * @triggering: Triggering type as provided by ACPI.
 331 * @polarity: Interrupt polarity as provided by ACPI.
 332 * @shareable: Whether or not the interrupt is shareable.
 333 */
 334unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
 335{
 336        unsigned long flags;
 337
 338        if (triggering == ACPI_LEVEL_SENSITIVE)
 339                flags = polarity == ACPI_ACTIVE_LOW ?
 340                        IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL;
 341        else
 342                flags = polarity == ACPI_ACTIVE_LOW ?
 343                        IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;
 344
 345        if (shareable == ACPI_SHARED)
 346                flags |= IORESOURCE_IRQ_SHAREABLE;
 347
 348        return flags | IORESOURCE_IRQ;
 349}
 350EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
 351
 352/**
 353 * acpi_dev_get_irq_type - Determine irq type.
 354 * @triggering: Triggering type as provided by ACPI.
 355 * @polarity: Interrupt polarity as provided by ACPI.
 356 */
 357unsigned int acpi_dev_get_irq_type(int triggering, int polarity)
 358{
 359        switch (polarity) {
 360        case ACPI_ACTIVE_LOW:
 361                return triggering == ACPI_EDGE_SENSITIVE ?
 362                       IRQ_TYPE_EDGE_FALLING :
 363                       IRQ_TYPE_LEVEL_LOW;
 364        case ACPI_ACTIVE_HIGH:
 365                return triggering == ACPI_EDGE_SENSITIVE ?
 366                       IRQ_TYPE_EDGE_RISING :
 367                       IRQ_TYPE_LEVEL_HIGH;
 368        case ACPI_ACTIVE_BOTH:
 369                if (triggering == ACPI_EDGE_SENSITIVE)
 370                        return IRQ_TYPE_EDGE_BOTH;
 371        default:
 372                return IRQ_TYPE_NONE;
 373        }
 374}
 375EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);
 376
 377static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
 378{
 379        res->start = gsi;
 380        res->end = gsi;
 381        res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET;
 382}
 383
 384static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
 385                                     u8 triggering, u8 polarity, u8 shareable,
 386                                     bool legacy)
 387{
 388        int irq, p, t;
 389
 390        if (!valid_IRQ(gsi)) {
 391                acpi_dev_irqresource_disabled(res, gsi);
 392                return;
 393        }
 394
 395        /*
 396         * In IO-APIC mode, use overrided attribute. Two reasons:
 397         * 1. BIOS bug in DSDT
 398         * 2. BIOS uses IO-APIC mode Interrupt Source Override
 399         *
 400         * We do this only if we are dealing with IRQ() or IRQNoFlags()
 401         * resource (the legacy ISA resources). With modern ACPI 5 devices
 402         * using extended IRQ descriptors we take the IRQ configuration
 403         * from _CRS directly.
 404         */
 405        if (legacy && !acpi_get_override_irq(gsi, &t, &p)) {
 406                u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
 407                u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
 408
 409                if (triggering != trig || polarity != pol) {
 410                        pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi,
 411                                   t ? "level" : "edge", p ? "low" : "high");
 412                        triggering = trig;
 413                        polarity = pol;
 414                }
 415        }
 416
 417        res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
 418        irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
 419        if (irq >= 0) {
 420                res->start = irq;
 421                res->end = irq;
 422        } else {
 423                acpi_dev_irqresource_disabled(res, gsi);
 424        }
 425}
 426
 427/**
 428 * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.
 429 * @ares: Input ACPI resource object.
 430 * @index: Index into the array of GSIs represented by the resource.
 431 * @res: Output generic resource object.
 432 *
 433 * Check if the given ACPI resource object represents an interrupt resource
 434 * and @index does not exceed the resource's interrupt count (true is returned
 435 * in that case regardless of the results of the other checks)).  If that's the
 436 * case, register the GSI corresponding to @index from the array of interrupts
 437 * represented by the resource and populate the generic resource object pointed
 438 * to by @res accordingly.  If the registration of the GSI is not successful,
 439 * IORESOURCE_DISABLED will be set it that object's flags.
 440 *
 441 * Return:
 442 * 1) false with res->flags setting to zero: not the expected resource type
 443 * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
 444 * 3) true: valid assigned resource
 445 */
 446bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
 447                                 struct resource *res)
 448{
 449        struct acpi_resource_irq *irq;
 450        struct acpi_resource_extended_irq *ext_irq;
 451
 452        switch (ares->type) {
 453        case ACPI_RESOURCE_TYPE_IRQ:
 454                /*
 455                 * Per spec, only one interrupt per descriptor is allowed in
 456                 * _CRS, but some firmware violates this, so parse them all.
 457                 */
 458                irq = &ares->data.irq;
 459                if (index >= irq->interrupt_count) {
 460                        acpi_dev_irqresource_disabled(res, 0);
 461                        return false;
 462                }
 463                acpi_dev_get_irqresource(res, irq->interrupts[index],
 464                                         irq->triggering, irq->polarity,
 465                                         irq->sharable, true);
 466                break;
 467        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 468                ext_irq = &ares->data.extended_irq;
 469                if (index >= ext_irq->interrupt_count) {
 470                        acpi_dev_irqresource_disabled(res, 0);
 471                        return false;
 472                }
 473                acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
 474                                         ext_irq->triggering, ext_irq->polarity,
 475                                         ext_irq->sharable, false);
 476                break;
 477        default:
 478                res->flags = 0;
 479                return false;
 480        }
 481
 482        return true;
 483}
 484EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
 485
 486/**
 487 * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().
 488 * @list: The head of the resource list to free.
 489 */
 490void acpi_dev_free_resource_list(struct list_head *list)
 491{
 492        resource_list_free(list);
 493}
 494EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
 495
 496struct res_proc_context {
 497        struct list_head *list;
 498        int (*preproc)(struct acpi_resource *, void *);
 499        void *preproc_data;
 500        int count;
 501        int error;
 502};
 503
 504static acpi_status acpi_dev_new_resource_entry(struct resource_win *win,
 505                                               struct res_proc_context *c)
 506{
 507        struct resource_entry *rentry;
 508
 509        rentry = resource_list_create_entry(NULL, 0);
 510        if (!rentry) {
 511                c->error = -ENOMEM;
 512                return AE_NO_MEMORY;
 513        }
 514        *rentry->res = win->res;
 515        rentry->offset = win->offset;
 516        resource_list_add_tail(rentry, c->list);
 517        c->count++;
 518        return AE_OK;
 519}
 520
 521static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
 522                                             void *context)
 523{
 524        struct res_proc_context *c = context;
 525        struct resource_win win;
 526        struct resource *res = &win.res;
 527        int i;
 528
 529        if (c->preproc) {
 530                int ret;
 531
 532                ret = c->preproc(ares, c->preproc_data);
 533                if (ret < 0) {
 534                        c->error = ret;
 535                        return AE_CTRL_TERMINATE;
 536                } else if (ret > 0) {
 537                        return AE_OK;
 538                }
 539        }
 540
 541        memset(&win, 0, sizeof(win));
 542
 543        if (acpi_dev_resource_memory(ares, res)
 544            || acpi_dev_resource_io(ares, res)
 545            || acpi_dev_resource_address_space(ares, &win)
 546            || acpi_dev_resource_ext_address_space(ares, &win))
 547                return acpi_dev_new_resource_entry(&win, c);
 548
 549        for (i = 0; acpi_dev_resource_interrupt(ares, i, res); i++) {
 550                acpi_status status;
 551
 552                status = acpi_dev_new_resource_entry(&win, c);
 553                if (ACPI_FAILURE(status))
 554                        return status;
 555        }
 556
 557        return AE_OK;
 558}
 559
 560/**
 561 * acpi_dev_get_resources - Get current resources of a device.
 562 * @adev: ACPI device node to get the resources for.
 563 * @list: Head of the resultant list of resources (must be empty).
 564 * @preproc: The caller's preprocessing routine.
 565 * @preproc_data: Pointer passed to the caller's preprocessing routine.
 566 *
 567 * Evaluate the _CRS method for the given device node and process its output by
 568 * (1) executing the @preproc() rountine provided by the caller, passing the
 569 * resource pointer and @preproc_data to it as arguments, for each ACPI resource
 570 * returned and (2) converting all of the returned ACPI resources into struct
 571 * resource objects if possible.  If the return value of @preproc() in step (1)
 572 * is different from 0, step (2) is not applied to the given ACPI resource and
 573 * if that value is negative, the whole processing is aborted and that value is
 574 * returned as the final error code.
 575 *
 576 * The resultant struct resource objects are put on the list pointed to by
 577 * @list, that must be empty initially, as members of struct resource_entry
 578 * objects.  Callers of this routine should use %acpi_dev_free_resource_list() to
 579 * free that list.
 580 *
 581 * The number of resources in the output list is returned on success, an error
 582 * code reflecting the error condition is returned otherwise.
 583 */
 584int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
 585                           int (*preproc)(struct acpi_resource *, void *),
 586                           void *preproc_data)
 587{
 588        struct res_proc_context c;
 589        acpi_status status;
 590
 591        if (!adev || !adev->handle || !list_empty(list))
 592                return -EINVAL;
 593
 594        if (!acpi_has_method(adev->handle, METHOD_NAME__CRS))
 595                return 0;
 596
 597        c.list = list;
 598        c.preproc = preproc;
 599        c.preproc_data = preproc_data;
 600        c.count = 0;
 601        c.error = 0;
 602        status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
 603                                     acpi_dev_process_resource, &c);
 604        if (ACPI_FAILURE(status)) {
 605                acpi_dev_free_resource_list(list);
 606                return c.error ? c.error : -EIO;
 607        }
 608
 609        return c.count;
 610}
 611EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
 612
 613/**
 614 * acpi_dev_filter_resource_type - Filter ACPI resource according to resource
 615 *                                 types
 616 * @ares: Input ACPI resource object.
 617 * @types: Valid resource types of IORESOURCE_XXX
 618 *
 619 * This is a helper function to support acpi_dev_get_resources(), which filters
 620 * ACPI resource objects according to resource types.
 621 */
 622int acpi_dev_filter_resource_type(struct acpi_resource *ares,
 623                                  unsigned long types)
 624{
 625        unsigned long type = 0;
 626
 627        switch (ares->type) {
 628        case ACPI_RESOURCE_TYPE_MEMORY24:
 629        case ACPI_RESOURCE_TYPE_MEMORY32:
 630        case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 631                type = IORESOURCE_MEM;
 632                break;
 633        case ACPI_RESOURCE_TYPE_IO:
 634        case ACPI_RESOURCE_TYPE_FIXED_IO:
 635                type = IORESOURCE_IO;
 636                break;
 637        case ACPI_RESOURCE_TYPE_IRQ:
 638        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 639                type = IORESOURCE_IRQ;
 640                break;
 641        case ACPI_RESOURCE_TYPE_DMA:
 642        case ACPI_RESOURCE_TYPE_FIXED_DMA:
 643                type = IORESOURCE_DMA;
 644                break;
 645        case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 646                type = IORESOURCE_REG;
 647                break;
 648        case ACPI_RESOURCE_TYPE_ADDRESS16:
 649        case ACPI_RESOURCE_TYPE_ADDRESS32:
 650        case ACPI_RESOURCE_TYPE_ADDRESS64:
 651        case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
 652                if (ares->data.address.resource_type == ACPI_MEMORY_RANGE)
 653                        type = IORESOURCE_MEM;
 654                else if (ares->data.address.resource_type == ACPI_IO_RANGE)
 655                        type = IORESOURCE_IO;
 656                else if (ares->data.address.resource_type ==
 657                         ACPI_BUS_NUMBER_RANGE)
 658                        type = IORESOURCE_BUS;
 659                break;
 660        default:
 661                break;
 662        }
 663
 664        return (type & types) ? 0 : 1;
 665}
 666EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
 667