linux/drivers/pci/pci-acpi.c
<<
>>
Prefs
   1/*
   2 * File:        pci-acpi.c
   3 * Purpose:     Provide PCI support in ACPI
   4 *
   5 * Copyright (C) 2005 David Shaohua Li <shaohua.li@intel.com>
   6 * Copyright (C) 2004 Tom Long Nguyen <tom.l.nguyen@intel.com>
   7 * Copyright (C) 2004 Intel Corp.
   8 */
   9
  10#include <linux/delay.h>
  11#include <linux/init.h>
  12#include <linux/pci.h>
  13#include <linux/module.h>
  14#include <linux/pci-aspm.h>
  15#include <acpi/acpi.h>
  16#include <acpi/acnamesp.h>
  17#include <acpi/acresrc.h>
  18#include <acpi/acpi_bus.h>
  19
  20#include <linux/pci-acpi.h>
  21#include "pci.h"
  22
  23struct acpi_osc_data {
  24        acpi_handle handle;
  25        u32 support_set;
  26        u32 control_set;
  27        int is_queried;
  28        u32 query_result;
  29        struct list_head sibiling;
  30};
  31static LIST_HEAD(acpi_osc_data_list);
  32
  33struct acpi_osc_args {
  34        u32 capbuf[3];
  35        u32 query_result;
  36};
  37
  38static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
  39{
  40        struct acpi_osc_data *data;
  41
  42        list_for_each_entry(data, &acpi_osc_data_list, sibiling) {
  43                if (data->handle == handle)
  44                        return data;
  45        }
  46        data = kzalloc(sizeof(*data), GFP_KERNEL);
  47        if (!data)
  48                return NULL;
  49        INIT_LIST_HEAD(&data->sibiling);
  50        data->handle = handle;
  51        list_add_tail(&data->sibiling, &acpi_osc_data_list);
  52        return data;
  53}
  54
  55static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
  56                          0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
  57
  58static acpi_status acpi_run_osc(acpi_handle handle,
  59                                struct acpi_osc_args *osc_args)
  60{
  61        acpi_status status;
  62        struct acpi_object_list input;
  63        union acpi_object in_params[4];
  64        struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
  65        union acpi_object *out_obj;
  66        u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE];
  67
  68        /* Setting up input parameters */
  69        input.count = 4;
  70        input.pointer = in_params;
  71        in_params[0].type               = ACPI_TYPE_BUFFER;
  72        in_params[0].buffer.length      = 16;
  73        in_params[0].buffer.pointer     = OSC_UUID;
  74        in_params[1].type               = ACPI_TYPE_INTEGER;
  75        in_params[1].integer.value      = 1;
  76        in_params[2].type               = ACPI_TYPE_INTEGER;
  77        in_params[2].integer.value      = 3;
  78        in_params[3].type               = ACPI_TYPE_BUFFER;
  79        in_params[3].buffer.length      = 12;
  80        in_params[3].buffer.pointer     = (u8 *)osc_args->capbuf;
  81
  82        status = acpi_evaluate_object(handle, "_OSC", &input, &output);
  83        if (ACPI_FAILURE(status))
  84                return status;
  85
  86        out_obj = output.pointer;
  87        if (out_obj->type != ACPI_TYPE_BUFFER) {
  88                printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n");
  89                status = AE_TYPE;
  90                goto out_kfree;
  91        }
  92        osc_dw0 = *((u32 *)out_obj->buffer.pointer);
  93        if (osc_dw0) {
  94                if (osc_dw0 & OSC_REQUEST_ERROR)
  95                        printk(KERN_DEBUG "_OSC request fails\n"); 
  96                if (osc_dw0 & OSC_INVALID_UUID_ERROR)
  97                        printk(KERN_DEBUG "_OSC invalid UUID\n"); 
  98                if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
  99                        printk(KERN_DEBUG "_OSC invalid revision\n"); 
 100                if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
 101                        if (flags & OSC_QUERY_ENABLE)
 102                                goto out_success;
 103                        printk(KERN_DEBUG "_OSC FW not grant req. control\n");
 104                        status = AE_SUPPORT;
 105                        goto out_kfree;
 106                }
 107                status = AE_ERROR;
 108                goto out_kfree;
 109        }
 110out_success:
 111        if (flags & OSC_QUERY_ENABLE)
 112                osc_args->query_result =
 113                        *((u32 *)(out_obj->buffer.pointer + 8));
 114        status = AE_OK;
 115
 116out_kfree:
 117        kfree(output.pointer);
 118        return status;
 119}
 120
 121static acpi_status acpi_query_osc(acpi_handle handle,
 122                                  u32 level, void *context, void **retval)
 123{
 124        acpi_status status;
 125        struct acpi_osc_data *osc_data;
 126        u32 flags = (unsigned long)context, support_set;
 127        acpi_handle tmp;
 128        struct acpi_osc_args osc_args;
 129
 130        status = acpi_get_handle(handle, "_OSC", &tmp);
 131        if (ACPI_FAILURE(status))
 132                return status;
 133
 134        osc_data = acpi_get_osc_data(handle);
 135        if (!osc_data) {
 136                printk(KERN_ERR "acpi osc data array is full\n");
 137                return AE_ERROR;
 138        }
 139
 140        /* do _OSC query for all possible controls */
 141        support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS);
 142        osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
 143        osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
 144        osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
 145
 146        status = acpi_run_osc(handle, &osc_args);
 147        if (ACPI_SUCCESS(status)) {
 148                osc_data->support_set = support_set;
 149                osc_data->query_result = osc_args.query_result;
 150                osc_data->is_queried = 1;
 151        }
 152
 153        return status;
 154}
 155
 156/**
 157 * __pci_osc_support_set - register OS support to Firmware
 158 * @flags: OS support bits
 159 * @hid: hardware ID
 160 *
 161 * Update OS support fields and doing a _OSC Query to obtain an update
 162 * from Firmware on supported control bits.
 163 **/
 164acpi_status __pci_osc_support_set(u32 flags, const char *hid)
 165{
 166        if (!(flags & OSC_SUPPORT_MASKS))
 167                return AE_TYPE;
 168
 169        acpi_get_devices(hid, acpi_query_osc,
 170                         (void *)(unsigned long)flags, NULL);
 171        return AE_OK;
 172}
 173
 174/**
 175 * pci_osc_control_set - commit requested control to Firmware
 176 * @handle: acpi_handle for the target ACPI object
 177 * @flags: driver's requested control bits
 178 *
 179 * Attempt to take control from Firmware on requested control bits.
 180 **/
 181acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
 182{
 183        acpi_status status;
 184        u32 ctrlset, control_set;
 185        acpi_handle tmp;
 186        struct acpi_osc_data *osc_data;
 187        struct acpi_osc_args osc_args;
 188
 189        status = acpi_get_handle(handle, "_OSC", &tmp);
 190        if (ACPI_FAILURE(status))
 191                return status;
 192
 193        osc_data = acpi_get_osc_data(handle);
 194        if (!osc_data) {
 195                printk(KERN_ERR "acpi osc data array is full\n");
 196                return AE_ERROR;
 197        }
 198
 199        ctrlset = (flags & OSC_CONTROL_MASKS);
 200        if (!ctrlset)
 201                return AE_TYPE;
 202
 203        if (osc_data->is_queried &&
 204            ((osc_data->query_result & ctrlset) != ctrlset))
 205                return AE_SUPPORT;
 206
 207        control_set = osc_data->control_set | ctrlset;
 208        osc_args.capbuf[OSC_QUERY_TYPE] = 0;
 209        osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set;
 210        osc_args.capbuf[OSC_CONTROL_TYPE] = control_set;
 211        status = acpi_run_osc(handle, &osc_args);
 212        if (ACPI_SUCCESS(status))
 213                osc_data->control_set = control_set;
 214
 215        return status;
 216}
 217EXPORT_SYMBOL(pci_osc_control_set);
 218
 219/*
 220 * _SxD returns the D-state with the highest power
 221 * (lowest D-state number) supported in the S-state "x".
 222 *
 223 * If the devices does not have a _PRW
 224 * (Power Resources for Wake) supporting system wakeup from "x"
 225 * then the OS is free to choose a lower power (higher number
 226 * D-state) than the return value from _SxD.
 227 *
 228 * But if _PRW is enabled at S-state "x", the OS
 229 * must not choose a power lower than _SxD --
 230 * unless the device has an _SxW method specifying
 231 * the lowest power (highest D-state number) the device
 232 * may enter while still able to wake the system.
 233 *
 234 * ie. depending on global OS policy:
 235 *
 236 * if (_PRW at S-state x)
 237 *      choose from highest power _SxD to lowest power _SxW
 238 * else // no _PRW at S-state x
 239 *      choose highest power _SxD or any lower power
 240 */
 241
 242static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
 243{
 244        int acpi_state;
 245
 246        acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL);
 247        if (acpi_state < 0)
 248                return PCI_POWER_ERROR;
 249
 250        switch (acpi_state) {
 251        case ACPI_STATE_D0:
 252                return PCI_D0;
 253        case ACPI_STATE_D1:
 254                return PCI_D1;
 255        case ACPI_STATE_D2:
 256                return PCI_D2;
 257        case ACPI_STATE_D3:
 258                return PCI_D3hot;
 259        }
 260        return PCI_POWER_ERROR;
 261}
 262
 263static bool acpi_pci_power_manageable(struct pci_dev *dev)
 264{
 265        acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
 266
 267        return handle ? acpi_bus_power_manageable(handle) : false;
 268}
 269
 270static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 271{
 272        acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
 273        acpi_handle tmp;
 274        static const u8 state_conv[] = {
 275                [PCI_D0] = ACPI_STATE_D0,
 276                [PCI_D1] = ACPI_STATE_D1,
 277                [PCI_D2] = ACPI_STATE_D2,
 278                [PCI_D3hot] = ACPI_STATE_D3,
 279                [PCI_D3cold] = ACPI_STATE_D3
 280        };
 281        int error = -EINVAL;
 282
 283        /* If the ACPI device has _EJ0, ignore the device */
 284        if (!handle || ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
 285                return -ENODEV;
 286
 287        switch (state) {
 288        case PCI_D0:
 289        case PCI_D1:
 290        case PCI_D2:
 291        case PCI_D3hot:
 292        case PCI_D3cold:
 293                error = acpi_bus_set_power(handle, state_conv[state]);
 294        }
 295
 296        if (!error)
 297                dev_printk(KERN_INFO, &dev->dev,
 298                                "power state changed by ACPI to D%d\n", state);
 299
 300        return error;
 301}
 302
 303static bool acpi_pci_can_wakeup(struct pci_dev *dev)
 304{
 305        acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
 306
 307        return handle ? acpi_bus_can_wakeup(handle) : false;
 308}
 309
 310static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
 311{
 312        int error = acpi_pm_device_sleep_wake(&dev->dev, enable);
 313
 314        if (!error)
 315                dev_printk(KERN_INFO, &dev->dev,
 316                                "wake-up capability %s by ACPI\n",
 317                                enable ? "enabled" : "disabled");
 318        return error;
 319}
 320
 321static struct pci_platform_pm_ops acpi_pci_platform_pm = {
 322        .is_manageable = acpi_pci_power_manageable,
 323        .set_state = acpi_pci_set_power_state,
 324        .choose_state = acpi_pci_choose_state,
 325        .can_wakeup = acpi_pci_can_wakeup,
 326        .sleep_wake = acpi_pci_sleep_wake,
 327};
 328
 329/* ACPI bus type */
 330static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 331{
 332        struct pci_dev * pci_dev;
 333        acpi_integer    addr;
 334
 335        pci_dev = to_pci_dev(dev);
 336        /* Please ref to ACPI spec for the syntax of _ADR */
 337        addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
 338        *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
 339        if (!*handle)
 340                return -ENODEV;
 341        return 0;
 342}
 343
 344static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
 345{
 346        int num;
 347        unsigned int seg, bus;
 348
 349        /*
 350         * The string should be the same as root bridge's name
 351         * Please look at 'pci_scan_bus_parented'
 352         */
 353        num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus);
 354        if (num != 2)
 355                return -ENODEV;
 356        *handle = acpi_get_pci_rootbridge_handle(seg, bus);
 357        if (!*handle)
 358                return -ENODEV;
 359        return 0;
 360}
 361
 362static struct acpi_bus_type acpi_pci_bus = {
 363        .bus = &pci_bus_type,
 364        .find_device = acpi_pci_find_device,
 365        .find_bridge = acpi_pci_find_root_bridge,
 366};
 367
 368static int __init acpi_pci_init(void)
 369{
 370        int ret;
 371
 372        if (acpi_gbl_FADT.boot_flags & BAF_MSI_NOT_SUPPORTED) {
 373                printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n");
 374                pci_no_msi();
 375        }
 376
 377        if (acpi_gbl_FADT.boot_flags & BAF_PCIE_ASPM_CONTROL) {
 378                printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
 379                pcie_no_aspm();
 380        }
 381
 382        ret = register_acpi_bus_type(&acpi_pci_bus);
 383        if (ret)
 384                return 0;
 385        pci_set_platform_pm(&acpi_pci_platform_pm);
 386        return 0;
 387}
 388arch_initcall(acpi_pci_init);
 389
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.