aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-01-09 03:39:43 -0500
committerLen Brown <len.brown@intel.com>2009-01-09 03:39:43 -0500
commitb2576e1d4408e134e2188c967b1f28af39cd79d4 (patch)
tree004f3c82faab760f304ce031d6d2f572e7746a50 /drivers/pci/pci-acpi.c
parent3cc8a5f4ba91f67bbdb81a43a99281a26aab8d77 (diff)
parent2150edc6c5cf00f7adb54538b9ea2a3e9cedca3f (diff)
Merge branch 'linus' into release
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c82
1 files changed, 38 insertions, 44 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 9d976d51d406..deea8a187eb8 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -22,13 +22,14 @@ struct acpi_osc_data {
22 acpi_handle handle; 22 acpi_handle handle;
23 u32 support_set; 23 u32 support_set;
24 u32 control_set; 24 u32 control_set;
25 u32 control_query;
26 int is_queried;
25 struct list_head sibiling; 27 struct list_head sibiling;
26}; 28};
27static LIST_HEAD(acpi_osc_data_list); 29static LIST_HEAD(acpi_osc_data_list);
28 30
29struct acpi_osc_args { 31struct acpi_osc_args {
30 u32 capbuf[3]; 32 u32 capbuf[3];
31 u32 ctrl_result;
32}; 33};
33 34
34static DEFINE_MUTEX(pci_acpi_lock); 35static DEFINE_MUTEX(pci_acpi_lock);
@@ -54,7 +55,7 @@ static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
54 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; 55 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
55 56
56static acpi_status acpi_run_osc(acpi_handle handle, 57static acpi_status acpi_run_osc(acpi_handle handle,
57 struct acpi_osc_args *osc_args) 58 struct acpi_osc_args *osc_args, u32 *retval)
58{ 59{
59 acpi_status status; 60 acpi_status status;
60 struct acpi_object_list input; 61 struct acpi_object_list input;
@@ -110,8 +111,7 @@ static acpi_status acpi_run_osc(acpi_handle handle,
110 goto out_kfree; 111 goto out_kfree;
111 } 112 }
112out_success: 113out_success:
113 osc_args->ctrl_result = 114 *retval = *((u32 *)(out_obj->buffer.pointer + 8));
114 *((u32 *)(out_obj->buffer.pointer + 8));
115 status = AE_OK; 115 status = AE_OK;
116 116
117out_kfree: 117out_kfree:
@@ -119,11 +119,10 @@ out_kfree:
119 return status; 119 return status;
120} 120}
121 121
122static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data, 122static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data)
123 u32 *result)
124{ 123{
125 acpi_status status; 124 acpi_status status;
126 u32 support_set; 125 u32 support_set, result;
127 struct acpi_osc_args osc_args; 126 struct acpi_osc_args osc_args;
128 127
129 /* do _OSC query for all possible controls */ 128 /* do _OSC query for all possible controls */
@@ -132,56 +131,45 @@ static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data,
132 osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set; 131 osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
133 osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; 132 osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
134 133
135 status = acpi_run_osc(osc_data->handle, &osc_args); 134 status = acpi_run_osc(osc_data->handle, &osc_args, &result);
136 if (ACPI_SUCCESS(status)) { 135 if (ACPI_SUCCESS(status)) {
137 osc_data->support_set = support_set; 136 osc_data->support_set = support_set;
138 *result = osc_args.ctrl_result; 137 osc_data->control_query = result;
138 osc_data->is_queried = 1;
139 } 139 }
140 140
141 return status; 141 return status;
142} 142}
143 143
144static acpi_status acpi_query_osc(acpi_handle handle, 144/*
145 u32 level, void *context, void **retval) 145 * pci_acpi_osc_support: Invoke _OSC indicating support for the given feature
146 * @flags: Bitmask of flags to support
147 *
148 * See the ACPI spec for the definition of the flags
149 */
150int pci_acpi_osc_support(acpi_handle handle, u32 flags)
146{ 151{
147 acpi_status status; 152 acpi_status status;
148 struct acpi_osc_data *osc_data;
149 u32 flags = (unsigned long)context, dummy;
150 acpi_handle tmp; 153 acpi_handle tmp;
154 struct acpi_osc_data *osc_data;
155 int rc = 0;
151 156
152 status = acpi_get_handle(handle, "_OSC", &tmp); 157 status = acpi_get_handle(handle, "_OSC", &tmp);
153 if (ACPI_FAILURE(status)) 158 if (ACPI_FAILURE(status))
154 return AE_OK; 159 return -ENOTTY;
155 160
156 mutex_lock(&pci_acpi_lock); 161 mutex_lock(&pci_acpi_lock);
157 osc_data = acpi_get_osc_data(handle); 162 osc_data = acpi_get_osc_data(handle);
158 if (!osc_data) { 163 if (!osc_data) {
159 printk(KERN_ERR "acpi osc data array is full\n"); 164 printk(KERN_ERR "acpi osc data array is full\n");
165 rc = -ENOMEM;
160 goto out; 166 goto out;
161 } 167 }
162 168
163 __acpi_query_osc(flags, osc_data, &dummy); 169 __acpi_query_osc(flags, osc_data);
164out: 170out:
165 mutex_unlock(&pci_acpi_lock); 171 mutex_unlock(&pci_acpi_lock);
166 return AE_OK; 172 return rc;
167}
168
169/**
170 * __pci_osc_support_set - register OS support to Firmware
171 * @flags: OS support bits
172 * @hid: hardware ID
173 *
174 * Update OS support fields and doing a _OSC Query to obtain an update
175 * from Firmware on supported control bits.
176 **/
177acpi_status __pci_osc_support_set(u32 flags, const char *hid)
178{
179 if (!(flags & OSC_SUPPORT_MASKS))
180 return AE_TYPE;
181
182 acpi_get_devices(hid, acpi_query_osc,
183 (void *)(unsigned long)flags, NULL);
184 return AE_OK;
185} 173}
186 174
187/** 175/**
@@ -194,7 +182,7 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid)
194acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) 182acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
195{ 183{
196 acpi_status status; 184 acpi_status status;
197 u32 ctrlset, control_set, result; 185 u32 control_req, control_set, result;
198 acpi_handle tmp; 186 acpi_handle tmp;
199 struct acpi_osc_data *osc_data; 187 struct acpi_osc_data *osc_data;
200 struct acpi_osc_args osc_args; 188 struct acpi_osc_args osc_args;
@@ -211,28 +199,34 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
211 goto out; 199 goto out;
212 } 200 }
213 201
214 ctrlset = (flags & OSC_CONTROL_MASKS); 202 control_req = (flags & OSC_CONTROL_MASKS);
215 if (!ctrlset) { 203 if (!control_req) {
216 status = AE_TYPE; 204 status = AE_TYPE;
217 goto out; 205 goto out;
218 } 206 }
219 207
220 status = __acpi_query_osc(osc_data->support_set, osc_data, &result); 208 /* No need to evaluate _OSC if the control was already granted. */
221 if (ACPI_FAILURE(status)) 209 if ((osc_data->control_set & control_req) == control_req)
222 goto out; 210 goto out;
223 211
224 if ((result & ctrlset) != ctrlset) { 212 if (!osc_data->is_queried) {
213 status = __acpi_query_osc(osc_data->support_set, osc_data);
214 if (ACPI_FAILURE(status))
215 goto out;
216 }
217
218 if ((osc_data->control_query & control_req) != control_req) {
225 status = AE_SUPPORT; 219 status = AE_SUPPORT;
226 goto out; 220 goto out;
227 } 221 }
228 222
229 control_set = osc_data->control_set | ctrlset; 223 control_set = osc_data->control_set | control_req;
230 osc_args.capbuf[OSC_QUERY_TYPE] = 0; 224 osc_args.capbuf[OSC_QUERY_TYPE] = 0;
231 osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set; 225 osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set;
232 osc_args.capbuf[OSC_CONTROL_TYPE] = control_set; 226 osc_args.capbuf[OSC_CONTROL_TYPE] = control_set;
233 status = acpi_run_osc(handle, &osc_args); 227 status = acpi_run_osc(handle, &osc_args, &result);
234 if (ACPI_SUCCESS(status)) 228 if (ACPI_SUCCESS(status))
235 osc_data->control_set = control_set; 229 osc_data->control_set = result;
236out: 230out:
237 mutex_unlock(&pci_acpi_lock); 231 mutex_unlock(&pci_acpi_lock);
238 return status; 232 return status;
@@ -373,7 +367,7 @@ static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
373 * The string should be the same as root bridge's name 367 * The string should be the same as root bridge's name
374 * Please look at 'pci_scan_bus_parented' 368 * Please look at 'pci_scan_bus_parented'
375 */ 369 */
376 num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus); 370 num = sscanf(dev_name(dev), "pci%04x:%02x", &seg, &bus);
377 if (num != 2) 371 if (num != 2)
378 return -ENODEV; 372 return -ENODEV;
379 *handle = acpi_get_pci_rootbridge_handle(seg, bus); 373 *handle = acpi_get_pci_rootbridge_handle(seg, bus);