aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c92
1 files changed, 60 insertions, 32 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 7764768b6a0..dfe7c8e1b18 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -11,6 +11,7 @@
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/pci.h> 12#include <linux/pci.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/pci-aspm.h>
14#include <acpi/acpi.h> 15#include <acpi/acpi.h>
15#include <acpi/acnamesp.h> 16#include <acpi/acnamesp.h>
16#include <acpi/acresrc.h> 17#include <acpi/acresrc.h>
@@ -23,17 +24,17 @@ struct acpi_osc_data {
23 acpi_handle handle; 24 acpi_handle handle;
24 u32 support_set; 25 u32 support_set;
25 u32 control_set; 26 u32 control_set;
26 int is_queried;
27 u32 query_result;
28 struct list_head sibiling; 27 struct list_head sibiling;
29}; 28};
30static LIST_HEAD(acpi_osc_data_list); 29static LIST_HEAD(acpi_osc_data_list);
31 30
32struct acpi_osc_args { 31struct acpi_osc_args {
33 u32 capbuf[3]; 32 u32 capbuf[3];
34 u32 query_result; 33 u32 ctrl_result;
35}; 34};
36 35
36static DEFINE_MUTEX(pci_acpi_lock);
37
37static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) 38static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
38{ 39{
39 struct acpi_osc_data *data; 40 struct acpi_osc_data *data;
@@ -107,9 +108,8 @@ static acpi_status acpi_run_osc(acpi_handle handle,
107 goto out_kfree; 108 goto out_kfree;
108 } 109 }
109out_success: 110out_success:
110 if (flags & OSC_QUERY_ENABLE) 111 osc_args->ctrl_result =
111 osc_args->query_result = 112 *((u32 *)(out_obj->buffer.pointer + 8));
112 *((u32 *)(out_obj->buffer.pointer + 8));
113 status = AE_OK; 113 status = AE_OK;
114 114
115out_kfree: 115out_kfree:
@@ -117,41 +117,53 @@ out_kfree:
117 return status; 117 return status;
118} 118}
119 119
120static acpi_status acpi_query_osc(acpi_handle handle, 120static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data,
121 u32 level, void *context, void **retval) 121 u32 *result)
122{ 122{
123 acpi_status status; 123 acpi_status status;
124 struct acpi_osc_data *osc_data; 124 u32 support_set;
125 u32 flags = (unsigned long)context, support_set;
126 acpi_handle tmp;
127 struct acpi_osc_args osc_args; 125 struct acpi_osc_args osc_args;
128 126
129 status = acpi_get_handle(handle, "_OSC", &tmp);
130 if (ACPI_FAILURE(status))
131 return status;
132
133 osc_data = acpi_get_osc_data(handle);
134 if (!osc_data) {
135 printk(KERN_ERR "acpi osc data array is full\n");
136 return AE_ERROR;
137 }
138
139 /* do _OSC query for all possible controls */ 127 /* do _OSC query for all possible controls */
140 support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS); 128 support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS);
141 osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; 129 osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
142 osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set; 130 osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
143 osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; 131 osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
144 132
145 status = acpi_run_osc(handle, &osc_args); 133 status = acpi_run_osc(osc_data->handle, &osc_args);
146 if (ACPI_SUCCESS(status)) { 134 if (ACPI_SUCCESS(status)) {
147 osc_data->support_set = support_set; 135 osc_data->support_set = support_set;
148 osc_data->query_result = osc_args.query_result; 136 *result = osc_args.ctrl_result;
149 osc_data->is_queried = 1;
150 } 137 }
151 138
152 return status; 139 return status;
153} 140}
154 141
142static acpi_status acpi_query_osc(acpi_handle handle,
143 u32 level, void *context, void **retval)
144{
145 acpi_status status;
146 struct acpi_osc_data *osc_data;
147 u32 flags = (unsigned long)context, dummy;
148 acpi_handle tmp;
149
150 status = acpi_get_handle(handle, "_OSC", &tmp);
151 if (ACPI_FAILURE(status))
152 return AE_OK;
153
154 mutex_lock(&pci_acpi_lock);
155 osc_data = acpi_get_osc_data(handle);
156 if (!osc_data) {
157 printk(KERN_ERR "acpi osc data array is full\n");
158 goto out;
159 }
160
161 __acpi_query_osc(flags, osc_data, &dummy);
162out:
163 mutex_unlock(&pci_acpi_lock);
164 return AE_OK;
165}
166
155/** 167/**
156 * __pci_osc_support_set - register OS support to Firmware 168 * __pci_osc_support_set - register OS support to Firmware
157 * @flags: OS support bits 169 * @flags: OS support bits
@@ -180,7 +192,7 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid)
180acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) 192acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
181{ 193{
182 acpi_status status; 194 acpi_status status;
183 u32 ctrlset, control_set; 195 u32 ctrlset, control_set, result;
184 acpi_handle tmp; 196 acpi_handle tmp;
185 struct acpi_osc_data *osc_data; 197 struct acpi_osc_data *osc_data;
186 struct acpi_osc_args osc_args; 198 struct acpi_osc_args osc_args;
@@ -189,19 +201,28 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
189 if (ACPI_FAILURE(status)) 201 if (ACPI_FAILURE(status))
190 return status; 202 return status;
191 203
204 mutex_lock(&pci_acpi_lock);
192 osc_data = acpi_get_osc_data(handle); 205 osc_data = acpi_get_osc_data(handle);
193 if (!osc_data) { 206 if (!osc_data) {
194 printk(KERN_ERR "acpi osc data array is full\n"); 207 printk(KERN_ERR "acpi osc data array is full\n");
195 return AE_ERROR; 208 status = AE_ERROR;
209 goto out;
196 } 210 }
197 211
198 ctrlset = (flags & OSC_CONTROL_MASKS); 212 ctrlset = (flags & OSC_CONTROL_MASKS);
199 if (!ctrlset) 213 if (!ctrlset) {
200 return AE_TYPE; 214 status = AE_TYPE;
215 goto out;
216 }
201 217
202 if (osc_data->is_queried && 218 status = __acpi_query_osc(osc_data->support_set, osc_data, &result);
203 ((osc_data->query_result & ctrlset) != ctrlset)) 219 if (ACPI_FAILURE(status))
204 return AE_SUPPORT; 220 goto out;
221
222 if ((result & ctrlset) != ctrlset) {
223 status = AE_SUPPORT;
224 goto out;
225 }
205 226
206 control_set = osc_data->control_set | ctrlset; 227 control_set = osc_data->control_set | ctrlset;
207 osc_args.capbuf[OSC_QUERY_TYPE] = 0; 228 osc_args.capbuf[OSC_QUERY_TYPE] = 0;
@@ -210,7 +231,8 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
210 status = acpi_run_osc(handle, &osc_args); 231 status = acpi_run_osc(handle, &osc_args);
211 if (ACPI_SUCCESS(status)) 232 if (ACPI_SUCCESS(status))
212 osc_data->control_set = control_set; 233 osc_data->control_set = control_set;
213 234out:
235 mutex_unlock(&pci_acpi_lock);
214 return status; 236 return status;
215} 237}
216EXPORT_SYMBOL(pci_osc_control_set); 238EXPORT_SYMBOL(pci_osc_control_set);
@@ -372,6 +394,12 @@ static int __init acpi_pci_init(void)
372 printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n"); 394 printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n");
373 pci_no_msi(); 395 pci_no_msi();
374 } 396 }
397
398 if (acpi_gbl_FADT.boot_flags & BAF_PCIE_ASPM_CONTROL) {
399 printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
400 pcie_no_aspm();
401 }
402
375 ret = register_acpi_bus_type(&acpi_pci_bus); 403 ret = register_acpi_bus_type(&acpi_pci_bus);
376 if (ret) 404 if (ret)
377 return 0; 405 return 0;